\documentclass[12pt,UTF8]{book}
\usepackage[dvipsnames, svgnames, x11names, table, xcdraw]{xcolor}
\usepackage{ctex,fancyhdr,geometry,graphicx,float,subfigure,multirow,cancel,listings,tikz,hyperref,titlesec,amsmath}
%ctex表示载入中文
%fancyhdr表示设置页面风格
%geometry表示界面尺寸设置
%\textbf
%float
%subfigure
%multirow表示分栏
%cancel
%listings
%tikz
%hyperref
%titlesec
\usetikzlibrary{positioning, shapes.geometric}
\pagestyle{fancy}
\fancyhf{
	\lhead{}
	\chead{}
	\rhead{}
	\lfoot{}
	\cfoot{\songti\zihao{4}{---\ \thepage\ ---}}
	\rfoot{}
}
\setlength{\headheight}{15pt}%标题距离上方15pt
\renewcommand\headrulewidth{0pt}%头线消失
\renewcommand\footrulewidth{0pt}%脚线消失
\geometry{a4paper,
	left=3.18cm,
	right=3.18cm,
	top=2.54cm,
	bottom=2.54cm
}
\title{C语言学习笔记}
\author{袁林果}
\date{\today}
\titleformat{\subsubsection}[block]{\centering\normalfont\bfseries\color{red}}{\thesubsubsection}{1em}{}
\lstset{  
	language=C,                    % 设置语言为C
	basicstyle=\ttfamily\footnotesize, % 设置基本字体样式和大小
	keywordstyle=\color{blue}\bfseries, % 设置关键词的颜色和加粗
	commentstyle=\color{gray}\itshape,  % 设置注释的颜色和斜体
	stringstyle=\color{red},        % 设置字符串的颜色
	showstringspaces=false,         % 不显示字符串中的空格
	breaklines=true,                % 允许代码自动换行
	numbers=left,                   % 在左侧显示行号
	numberstyle=\tiny\color{gray},  % 设置行号的样式和颜色
	stepnumber=1,                   % 每行都显示行号
	numbersep=5pt,                  % 设置行号与代码之间的间隔
	frame=single,                   % 为代码块添加单线边框
	tabsize=4,                      % 设置Tab键相当于的空格数
	captionpos=t,                   % 将标题放在代码块顶部
	showspaces=false,               % 不显示空格
	showtabs=false,                 % 不显示制表符
	backgroundcolor=\color{white},  % 设置代码块的背景颜色
	columns=fullflexible,           % 允许列宽灵活调整
	morecomment=[s][\color{magenta}]{...}, % 例如，将"..."视为特殊注释并着色 
}  
\begin{document}
\maketitle
\pagestyle{plain}%设置页面页码
\thispagestyle{fancy}%设置页面风格
\newpage
\tableofcontents
\newpage
\part{序章$\bullet$前记}
\chapter{人机交互}
\section{怎样人机交互}
\subsection{语言$\bullet$指令}
语言是人和人，或者人和动物交流的一个方式，人和机器交流的语言就叫机器语言，常见的有\textit{C语言}、\textit{R语言}、\textit{python}、\textit{Java}……
\subsection{人和机器怎么交互}
最早的机器是由于电流操控，于是机器只知道通电和断电，于是乎也刚好对应住了，二进制的高电平(1)和低电平(0)，所以计算机的内存本质就是由0和1来组成。
\section{C语言的由来}
\subsection{C语言之父}
1966年，汤普森加入贝尔实验室。1968年，汤普森参与了贝尔实验室与麻省理工学院、通用电气公司联合开发的一个多用户分时操作系统，取名为Multics(多路信息计算系统)。

一年后，贝尔实验室认为Multics系统周期长、成本高、前景不佳，便决定撤出。汤普森非常失落，他自己写的一款叫做“star travel”的游戏就是完全基于Multics的，退出Multics项目意味着他将没有机器可以玩这个游戏了。

于是汤普森决定自己设计一个操作系统来玩游戏，他本来打算向实验室申请在DEC-10上写，然而没有申请到，只能找到了一台废弃已久的老式PDP-7小型机，虽然称为小型机，也有一个房间大。汤普森先在这台机器上重写了游戏，接着他用一周时间设计出操作系统的内核，再用一周时间创造出文件系统，一周时间写编辑器，一周时间写编译程序，最终在一个月内编写完了整个操作系统。汤普森将其命名为UNICS （UNiplexed Information and Computing System）。后面陆续做了一些改动和优化，便有了第一版UNIX操作系统。

\subsection{C语言的标准}
由于最初的C语言比以往的语言要好用很多，所以很多公司采用了C语言，但是每个公司或多或少都进行过微调，于是乎C语言的标准，就不同了，在1989年，由美国国家标准局(ANSI)颁布了C语言的第一个标准C89，后续又更新了C99、C11等。

C语言是编译型语言。
\subsection{常见的C语言编辑器以及编译器}\leavevmode\\
编译器：就是一边儿编译一边儿翻译成机器语言\\
编辑器：就是只能像记事本一样记录
\begin{enumerate}
	\item 编译器
	\begin{enumerate}
	\item Clang
	\item GCC
	\item WIN-TC
	\item MSVC(visual studio 2022 )
	\item Turbo C
	\end{enumerate}
	\item 编辑器
	\begin{enumerate}
	\item SUBLIME
	\end{enumerate}
\end{enumerate}
\section{使用visual studio 2022的一些注意事项}
\subsection{vs2022里面的{\color{red}\texttt{scanf()}}}
在vs2022里面对于{\color{red}\verb|scanf()|}函数是用{\color{red}\verb|scanf_s()|}来表示的，如果执意需要使用{\color{red}\verb|scanf()|}的话，需要在第一行，加上{\color{red}\verb|#define _CRT_SECURE_NO_WARNINGS|}
\part{C语言的基础知识}
\chapter{C语言入门}

\section{代码分析}
\begin{figure}[H] %H为当前位置,!htb为忽略美学标准,htbp为浮动图形
    \centering %图片居中
    \includegraphics[width=0.7\textwidth]{Holle Word代码} %插入图片,[]中设置图片大小,{}中是图片文件名
    \caption{Holle Word代码} %最终文档中希望显示的图片标题
    \label{fig.1} %用于文内引用的标签
\end{figure}\leavevmode\\
{\color{red}{\texttt{include}}}表示包含于这个.h为后缀的头文件\\
{\color{red}{\texttt{stdio}}}里面{\color{red}{\texttt{std}}}表示standard标准，{\color{red}{\texttt{i}}} 表示input输入，{\color{red}{\texttt{o}}} 表示output输出\\
{\color{red}{\texttt{int}}}以上是预处理(表示需要提前找到,程序需要用的东西(各种包))\\
{\color{red}{\texttt{int}}}以下是业务代码(就是要让计算机干的事情)\\
{\color{red}{\texttt{int}}}表示整个程序运行结果是整数\\
{\color{red}{\texttt{int main()}}}表示程序主入口\\
{\color{red}{\texttt{\{ \\ \}}}}表示在一个范围里面要运行的程序\\
{\color{red}{\texttt{printf();}}}输出语句\\
{\color{red}{\texttt{;}}}表示该行程序结束\\
{\color{red}{\texttt{return 0;}}}表示运行结果,输出0表示正常结束\\
\section{代码执行流程分析}
先需要{\color{red}{编写}}一个后缀为.c的C program language文件,然后进行vs{\color{red}{编译}}得到一个后缀为.obj的由0与1组成的文件,然后.obj文件与stdio.h{\color{red}{组合}}成为.exe文件(连接或者链接文件).
\chapter{核心语法}
\section{注释}

\subsection{单行注释}\leavevmode\\
{\color{red}{\verb|//|}}$\cdots\cdots\cdots$单行注释
\\
\verb|//|
\\
\verb|//|
\\
\verb|//|
\\
%\begin{figure}[H] %H为当前位置,!htb为忽略美学标准,htbp为浮动图形
%    \centering %图片居中
%    \includegraphics[width=0.7\textwidth]{单行注释.png} %插入图片,[]中设置图片大小,{}中是图片文件名
%    \caption{单行注释} %最终文档中希望显示的图片标题
%    \label{fig.2} %用于文内引用的标签
%\end{figure}

\subsection{多行注释}\leavevmode\\
{\color{red}{\texttt{/*}}}$\cdots\cdots\cdots${\color{red}{\texttt{*/}}}$\cdots\cdots\cdots$多行注释
\\
\verb|/*可以注释多行内容*/|
%\begin{figure}[H]
%    \centering
%    \includegraphics[width=0.7\textwidth]{多行注释.png}
%    \caption{多行注释}
%    \label{fig.3}
%\end{figure}

\section{关键字}
\section{常量}
\subsection{常量类型}
\begin{table}[H]
    \centering
    \begin{tabular}{|c|c|c|c|}
    \hline
    常量类型  & 说明 & \multicolumn{2}{c|}{举例} \\
    \hline
    整型常量  & 正数、负数、0 & 18 & 34        \\
    \hline
    实型常量  & 所有带小数点的数字 & 1.21 & 3.22      \\
    \hline
    字符常量  & 单引号引起来的字母、数字、英文符号(只能写一个字母) & 'a' & '22'      \\
    \hline
    字符串常量 & 双引号引起来 & "牛逼" & "abcdefg"  \\
    \hline     
    \end{tabular}
    \caption{常量类型}
    \label{biao.1}
\end{table}

\begin{figure}[H]
    \centering
    \includegraphics[width=1\textwidth]{常量举例.png}
   \caption{常量举例}
    \label{fig.4}
\end{figure}
\subsection{常量通识}
\begin{enumerate}
    \item {\heiti 实型常量首末为0,可以省略}\\
    如0.33333或者19.0之类的实变量0.33333的0可以省略写为.33333;\\
    19.0的末0可以省略写为19.
    \item {\heiti 科学计数法是实型常量,但是要写为E}\\
    如$1.255260000\ast 10^7$表示一个计算过程并不是实型变量\\
    如$1.255260000\mathrm{E}7$表示实型变量
\end{enumerate}

\subsection{输出常量}
\leavevmode\\
{\color{red}{\verb|printf(参数1,参数2)|}}$\cdots\cdots\cdots$打印函数\\
\begin{enumerate}
    \item \textbf{参数1}:输出内容最终样式,以字符串的形式体现
    \item \textbf{参数2}:填补内容
\end{enumerate}\leavevmode\\

{\color{red}{\verb|printf(参数1,参数2)|}}

\begin{table}[H]
    \centering
    \begin{tabular}{ |c|c|c| }
    \hline
    格式控制符(占位符) & 说明 & 单词 \\ \hline
    整型 & \texttt{\%d} & decimal \\ \hline
    实型 & \texttt{\%f} & floating-point \\ \hline
    字符 & \texttt{\%c} & character \\ \hline
    字符串 & \texttt{\%s} & string \\ \hline
	\end{tabular}
    \caption{占位符}
    \label{biao.2}
\end{table}
\begin{figure}[htp]
    \begin{minipage}[t]{0.48\textwidth}%t表示与文本对齐
    \centering
    \includegraphics[width=0.3\textheight]{输出变量}
    \caption{输出变量}
    \end{minipage}
    \begin{minipage}[t]{0.48\textwidth}%t表示与文本对齐
    \centering
    \includegraphics[width=1.191\textwidth]{输出变量端口}
    \caption{输出变量端口}
    \end{minipage}
    \label{fig.5}
\end{figure}

\subsection{常量的两个规则}\leavevmode\\
{\color{red}{\verb|\n|}}$\cdots\cdots\cdots$换行符
\begin{enumerate}
    \item 形如如图\ref{fig.6}第一行,需要一行中连续许多占位符的,需要依次排序才可使用,否者会报错.
    \begin{figure}[H]
        \centering 
        \includegraphics[width=0.7\textwidth]{打印符共识.png} 
        \caption{打印符共识}
        \label{fig.6}
    \end{figure}
    \item 形如如图\ref{fig.6}第二行,如若换行需要加入\verb|\n|
\end{enumerate}
\section{变量}
\subsection{变量的形式}\leavevmode\\
{\color{red}{数据类型+变量名+;\\
\verb|int a;| }}$\cdots\cdots\cdots$变量的定义格式
%\begin{lstlisting}[language=语言名称, caption=代码标题, label=代码标签] 你的代码 
%\end{lstlisting}
\begin{lstlisting}[language=C, caption=C语言变量示例, label=C.1]
#include <stdio.h>
int main()
{
    int a;
    a = 2;
    printf ("%d\n",a);
    return 0;
}
输出：2
\end{lstlisting}
\subsection{变量的基本常识}
\begin{enumerate}
    \item C program language只能存一个值
    \begin{lstlisting}[language=C, caption=C语言只能存一个值变量示例, label=C.2]
        #include <stdio.h>
        int main()
        {
            int a = 2;
            printf ("%d\n",a);
            a = 3;
            printf ("%d\n",a);
            return 0;
        }
        输出：2
              3
        \end{lstlisting}
    \item C program language变量名不允许重复定义
    \begin{lstlisting}[language=C, caption=C语言变量名重复导致错误变量示例, label=C.3]
        #include <stdio.h>
        int main()
        {
            int a = 2;
            int a = 3;不能同时对同一个变量赋值
            printf ("%d\n",a);
            return 0;
        }
        输出：报错
        \end{lstlisting}
    \item C program language一条语句可以定义多个变量
    \begin{lstlisting}[language=C, caption=C语言可定义多个变量变量示例, label=C.4]
        #include <stdio.h>
        int main()
        {
            int a = 2,b = 3,c = 4,d = 5;
            printf("%d%d%d%d\n", a, b, c, d);
            return 0;
        }
        输出：2345
        \end{lstlisting}
    \item C program language变量在使用之前一定要赋值
    \begin{lstlisting}[language=C, caption=C语言未赋值变量示例, label=C.5]
        #include <stdio.h>
        int main()
        {
            int a;
            printf("%d\n", a);
            return 0;
        }
        输出：报错,无法输出
        \end{lstlisting}
    \item C program language变量作用域范围(注：后续才会学到)
\end{enumerate}
\section{局部变量和全局变量}
写在括号外面的变量则称为该括号内的全局变量，写在括号内的则称之为局部变量，如代码\ref{C.ju}中：
{\color{red}\begin{lstlisting}[language=C, caption=C语言中的全局变量与局部变量, label=C.ju]	
int a = 10;
int main() 
	{
		int a = 100;
		printf("%p\n",a);
	}
	
输出100
\end{lstlisting}}
在全局变量名和局部变量名相同时(不建议把这两个变量设置为相同)，优先级是局部变量，因此输出为100
\section{计算机的存储规则}
\begin{enumerate}
	\item \textrm{文本Text储存}
	\begin{enumerate}
		\item \textbf{数字\ \textit{直接转二进制}}
		\item \textbf{字母\textit{ASCII码}}
		\item \textbf{汉字\textit{Windows查询GBK码表再转化为二进制}}
	\end{enumerate}
	\item 图像储存
	\textbf{像素+RBG比例}
	\item 声音储存
	\textbf{转换为对声音波形图采样再储存}
	\item 视频储存
	\textbf{图像加声音组合}
\end{enumerate}
\section{常见的进制}
可知一个任意多位的N进制数D均可展开为如下形式：
\begin{equation}
D=\sum_{i}^{n}k_i\times N^{i-1}
\end{equation}
\begin{enumerate}
	\item \textbf{二进制：}逢二进一,借二当一\\
	$(010101010101010)_B$
	\item \textbf{八进制：}(把二进制每三位$2^3$放在一组)逢八进一,借八当一\\
	$(010101010101010)_B=((010)(101)(010)(101)(010))_B=(25252)_O$
	\item \textbf{十进制：}逢十进一,借十当一\\
	$(010101010101010)_B=(0\times10^{14} +1\times10^{13}+0\times10^{12}+1\times10^{11}+0\times10^{10}+1\times10^9+0\times10^8+1\times10^7+0\times10^6+1\times10^5+0\times10^4+1\times10^3+0\times10^2+1\times10^1+0\times10^0)_B=(0\times2^{14} +1\times2^{13}+0\times2^{12}+1\times2^{11}+0\times2^{10}+1\times2^9+0\times2^8+1\times2^7+0\times2^6+1\times2^5+0\times2^4+1\times2^3+0\times2^2+1\times2^1+0\times2^0)_D=(10,922)_D$
	\item \textbf{十六进制；}(把二进制每四位$2^4$放在一组)逢\textrm{E}进一,借\textrm{E}当一\\
	$(010101010101010)_B=((0010)(1010)(1010)(1010))_B=(2AAA)_H$
\end{enumerate}
若在C program language中即为:{\color{red}\verb|0b|}代表二进制{\color{red}\verb|0|}代表八进制{\color{red}\verb|0x|}代表十六进制,输出方式如下:
\begin{figure}[H]
	\begin{minipage}[t]{0.48\textwidth}%t表示与文本对齐
		\centering
		\includegraphics[width=1\textwidth]{进制输出方式}
		\caption{输出变量}
	\end{minipage}
	\begin{minipage}[t]{0.48\textwidth}%t表示与文本对齐
		\centering
		\includegraphics[width=1.2\textwidth]{进制输出方式端口}
		\caption{输出变量端口}
	\end{minipage}
	\label{fig.7}
\end{figure}
\section{数据类型}\leavevmode\\
数据类型作用；
\begin{enumerate}
\item 变量中存储各种类型数据
\item 存储空间大小
\end{enumerate}
\subsection{计算机中的单位}
\begin{itemize}
	\item[] $1\mathrm{Byte}(\text{字节})=2^3\mathrm{bit}(\text{位})=8\mathrm{bit}(\text{位})$\\
	比特位就是2进制靠0和1来表达所有的信息
	\item[] $1\mathrm{KB}(\text{千字节})=2^{10}\mathrm{Byte}(\text{字节})=1024\mathrm{Byte}(\text{字节})$
	\item[] $1\mathrm{MB}(\text{兆字节})=2^{10}\mathrm{KB}(\text{字节})=1024\mathrm{KB}(\text{字节})$
\end{itemize}
\subsection{整型}
不同的数据类型所表示的范围和内存大小都不一样,由编译器来决定,可以用sizeof来确定,会遵守一个原则\verb|short|$\le$\verb|int|$\le$\verb|long|$\le$\verb|long long|.

有$1\mathrm{Byte}=2^3\mathrm{bit}=8\mathrm{bit}$

如为四个字节$4\times2^3$位,即(00000000 00000000 00000000 00000000)一共有$2^{4\times 2^3=2^32}=4294967296=2147483648$种变化同理可知\textit{short}、\textit{long}和\textit{long long}各自变化.
\\
{\color{red}{\verb|sizeof()|}}

也可以调用\verb|sizeof()|函数求\textit{short}、\textit{int}、\textit{long}和\textit{long long}各自长度(byte字节),如下图\ref{fig.8}
\begin{figure}[H]
	\begin{minipage}[t]{0.48\textwidth}%t表示与文本对齐
		\centering
		\includegraphics[width=1\textwidth]{sizeof函数使用格式}
		\caption{sizeof函数使用格式}
	\end{minipage}
	\begin{minipage}[t]{0.48\textwidth}%t表示与文本对齐
		\centering
		\includegraphics[width=1.2\textwidth]{sizeof函数使用格式输出}
		\caption{sizeof函数使用格式输出方式}
	\end{minipage}
	\label{fig.8}
\end{figure}
\begin{enumerate}
	\item \textbf{\textit{short短整型}}：{\color{red}{\verb|short|}}需要用{\color{red}{\verb|\%d|}}占位符.
	\item \textbf{\textit{int整型}}：{\color{red}{\verb|int|}}需要用{\color{red}{\verb|%d|}}占位符.
	\item \textbf{\textit{long长整型}}：{\color{red}{\verb|long|}}需要用{\color{red}{\verb|%ld|}}占位符,控制变量时候尾部要带一个L.
\begin{figure}[H]
	\centering
	\includegraphics[width=0.7\linewidth]{long型注意事项}
	\caption{long型注意事项}
	\label{fig:9}
\end{figure}
	\item \textbf{\textit{long long超长整型}}：{\color{red}{\verb|long long|}}需要用{\color{red}{\verb|%lld|}}占位符,控制变量时候尾部要带一个LL.
\begin{figure}[H]
	\centering
	\includegraphics[width=0.7\linewidth]{long long型注意事项}
	\caption{long long型注意事项}
	\label{fig:10}
\end{figure}
\end{enumerate}
\begin{table}[H]
	\begin{tabular}{|c|c|c|c|}
		\hline
		整数型号                  & 打印符号                  & 取值范围(32位$\sim$64位)                                       & 内存 \\ \hline
		short                 & \%d                   & -32768$\sim$32767                                        & 2  \\ \hline
		int                   & \%d                   & -2147483648$\sim$2147483647                              & 4  \\ \hline
		\multirow{2}{*}{long} & \multirow{2}{*}{\%ld} & 32位：-2147483648$\sim$2147483647 (10位数)                   & 4  \\ \cline{3-4} 
		&                       & 64位：-9223372036854775808$\sim$9223372036854775807 (19位数) & 8  \\ \hline
		long long             & \%lld                 & -9223372036854775808$\sim$9223372036854775807 (19位数)     & 8  \\ \hline
	\end{tabular}
\end{table}\leavevmode\\
倘若输入一个超过取值范围的数,就会报出一个错误数值.
\begin{figure}[H]
	\centering
	\includegraphics[width=0.5\linewidth]{输出超过取值范围的数报错}
	\caption{输出超过取值范围的数报错}
	\label{fig:11}
\end{figure}
\subsection{整数型的两个小常识}
\begin{enumerate}
	\item 整数型完整写法
		在C语言程序中整数完整写法{\color{red}{\verb|short|}}与{\color{red}{\verb|short int|}}等价,{\color{red}{\verb|int|}},{\color{red}{\verb|long|}}与{\color{red}{\verb|long int|}}等价{\color{red}{\verb|long long|}}与{\color{red}{\verb|long long int|}}等价.
		\begin{figure}[H]
			\centering
			\includegraphics[width=0.7\linewidth]{C语言中整数类型缩写与完整}
			\caption{C语言中整数类型缩写与完整}
			\label{fig:12}
		\end{figure}
		\begin{table}[H]
			\begin{tabular}{|c|c|}
			\hline
			缩写&完整版\\
			\hline
			short&short int\\
			\hline
			int&int\\
			\hline
			long&long int\\
			\hline
			long long&long long int\\
			\hline
			\end{tabular}
			\centering
		\end{table}
	\item {\color{red}{\verb|signed|}}与{\color{red}{\verb|unsigned|}}用法:\\
	{\color{red}{\verb|signed|}}表示有符号整数(正数、负数和0).\\
	{\color{red}{\verb|unsigned|}}表示无符号整数(正数).
	\begin{enumerate}
		{\color{red}{\zihao{3}\item  \verb|signed|与\verb|unsigned|只能用于整数否则会报错.
		\item \verb|unsigned|需要利用打印符\verb|%u|,而且遇到“$-$”会报错.}}
	\end{enumerate}
	\begin{figure}[H]
		\centering
		\includegraphics[width=0.7\linewidth]{C语言中有符号整数与无符号整数使用方法}
		\caption{C语言中有符号整数与无符号整数使用方法}
		\label{fig:13}
	\end{figure}
\end{enumerate}
\subsection{浮点型}
\begin{figure}[H]
	\begin{minipage}[t]{0.48\textwidth}%t表示与文本对齐
		\centering
		\includegraphics[width=1\textwidth]{浮点数输出}
		\caption{浮点数输出}
	\end{minipage}
	\begin{minipage}[t]{0.48\textwidth}%t表示与文本对齐
		\centering
		\includegraphics[width=1.2\textwidth]{浮点数输出端口}
		\caption{浮点数输出端口}
	\end{minipage}
	\label{fig.14}
\end{figure}\leavevmode\\
\textbf{\textit{float整型}}：{\color{red}\verb|float|}需要用{\color{red}{\verb|%f|}}占位符,控制变量时候尾部要带一个F.\\
\textbf{\textit{double整型}}：{\color{red}\verb|double|}需要用{\color{red}{\verb|%lf|}}占位符.\\
\textbf{\textit{long double整型}}：{\color{red}\verb|long double|}需要用{\color{red}{\verb|%lf|}}占位符,控制变量时候尾部要带一个L.\\
\begin{table}[H]
	\begin{tabular}{|c|c|c|}
		\hline
		整数 & 取值范围& 内存\\
		\hline
		float&(精确小数点后6位)$1.175 \times10^{-38} \sim3.402\times10^{38}$(38位) &4\\
		\hline
		double&(精确小数点后15位)$2.225\times10^{-308}\sim 1.797 \times10^{308}$(308位)& 8\\
		\hline
		long double&(精确小数点后18$\sim$19位)&8\\
		\hline
	\end{tabular}
\end{table}
\subsection{字符型}
\begin{figure}[H]
	\begin{minipage}[t]{0.48\textwidth}%t表示与文本对齐
		\centering
		\includegraphics[width=1\textwidth]{字符类型输出}
		\caption{字符类型输出}
	\end{minipage}
	\begin{minipage}[t]{0.48\textwidth}%t表示与文本对齐
		\centering
		\includegraphics[width=0.8\textwidth]{字符类型输出端口}
		\caption{字符类型输出端口}
	\end{minipage}
	\label{fig.15}
\end{figure}\leavevmode\\
\textbf{\textit{char型}}：{\color{red}{\verb|char|}}需要用{\color{red}{\verb|%c|}}占位符.

\begin{table}[H]
	\begin{tabular}{|c|c|c|}
		\hline
		整数 & 取值范围& 内存\\
		\hline
		char & ASCll码表中的字母数字,英文符号 & 1\\
		\hline
	\end{tabular}
\end{table}
\subsection{字符串}
同样需要用过{\color{red}{\verb|char|}}来定义,不同的是,需要标注需要用
几个字节,形式如同\\
{\color{red}{\verb|char a[6] = "qwq和";|}}其中a为\verb|char|形的一个变量名,[\ ]里面的数字为该变量所占用的字节(一般情况下,数字、字母、英语符号占用一个字节,汉字占用两个字节.并且中括号中的数字避免麻烦可以标大很多.),其中“和”字后有一个未显示的内容(\%0)占用一个字节,所以一共占用6个字节;并且字符串的占位符需要用\%s来表示.
\begin{lstlisting}[language=C, caption=C语言中的字符串的引用方法, label=C.6]
	int main()
	{
		char a[100];
		// 需求1:键盘录入女朋友的名字,并按照以下格式打印出来
		// 格式:我亲亲女朋友的名字为:XXX
		printf("请输入你女朋友名字：");
		scanf("%s", &a);
		printf("我亲亲女朋友的名字为:%s\n",a);
	}
\end{lstlisting}
\subsection{标识符}
\begin{enumerate}
	\item 硬性要求
	\begin{enumerate}
		\item 由数字、字母和下划线(\_)组成.
		\item 不能以数字开头.
		\item 不能是关键字.
		\item 区分大小写.
	\end{enumerate}
	\item 软性建议
	\begin{enumerate}
		\item 用英文单词,见名知意.
		\item 变量名全部小写.
		\item 代码文件名；全部小写,单词之间用下划线(\_)隔开,开头可以用数字.
	\end{enumerate}
\end{enumerate}
\section{键盘录入}\leavevmode\\
{\color{red}{\verb|scanf("符 ",&变量)|}}:为C语言的一个函数,作用键盘录入,是scanner format(格式\ 扫描仪)的缩写.\verb|scanf("打印符 ",&变量)|语法中,变量前面一定要有“\&”.\\
\verb|scanf|的作用:接受用户键盘输入的数据并赋值给对应的变量
\begin{lstlisting}[language=C, caption=C语言中的scanf函数使用方法, label=C.7]
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
	int a = 0;
	printf("请输入一个整数：");
	scanf("%d",&a);
	printf("变量a里面的值为：%d",a);
	return 0;
}
\end{lstlisting}
\begin{center}
\zihao{1} \verb|scanf|使用注意事项
\end{center}
\begin{enumerate}
	\item 在使用中若\verb|scanf("xxx%yyy",a);|,则在终端需要输入xxx(变量b)yyy才会输出这个a
	\item 占位符和后面的变量要一一对应
	\item 第一个参数中不写换行
	\item 直接写\verb|scanf|会报出安全问题
\end{enumerate}

\chapter{运算符}
\begin{table}[H]
	\centering
\begin{tabular}{|c|cccccc|}
	\hline
	\multicolumn{7}{|c|}{运算符}\\
	\hline
	名称&\multicolumn{6}{c|}{符号}\\
	\hline
	算术运算符 & \verb|+| & \verb|-| & \verb|*| & \verb|/| & \verb|%| &  \\
	\hline
	自增自减运算符 &\multicolumn{3}{c}{++} & \multicolumn{3}{c|}{-\,-}  \\
	\hline
	赋值运算符 & \verb|=| & \verb|+=| & \verb|-=| & \verb|*=| & \verb|/=| & \verb|%=| \\
	\hline
	关系运算符 & \verb|==| & \verb|!=| & \verb|>| & \verb|>=| & \verb|<| & \verb|<=| \\
	\hline
	逻辑运算符 & \multicolumn{2}{c}{!}  &\multicolumn{2}{c}{\&\&} & \multicolumn{2}{c|}{||}\\
	\hline
	三元运算符 & \multicolumn{6}{c|}{a>b?a:b} \\
	\hline
\end{tabular}
\end{table}
\section{算术运算符}
\subsection{算数运算符表}
\begin{table}[H]
	\centering
	\begin{tabular}{|c|c|}
		\hline
		\multicolumn{2}{|c|}{算术运算符}\\
		\hline
		符号&说明\\
		\hline
		\verb|+|&加\\
		\hline
		\verb|-|&减\\
		\hline
		\verb|*|&乘\\
		\hline
		\verb|/|&除\\
		\hline
		\verb|%|&取余\\
		\hline
	\end{tabular}
\end{table}
\subsection{算数运算符要求}
\begin{center}
	\zihao{1}符合数学运算
\end{center}
\begin{itemize}
	\item 通用细节
	\begin{enumerate}
		\item 整数计算,结果一定是个整数.
		\item 小数计算,结果一定是个小数.
		\item 整数和小数计算,结果一定是个小数.
		\item 小数直接参与计算,结果有可能不精确.
	\end{enumerate}
	\item 除法细节
	\begin{enumerate}
	\item 不能除以0.
	\end{enumerate}
	\item 取余的细节
	\begin{enumerate}
	\item 运算时的数据必须全为整数.
	\item 获取余数的正负是跟第一个数据保持正负的.
	\item 不能除以0.
	\end{enumerate}
\end{itemize}
\subsection{算数运算符的数值拆分公式}
\begin{lstlisting}[language=C, caption=C语言中的数值拆分公式, label=C.8]
个位:数值 / 1 % 10
十位:数值 /10 % 10
百位:数值 /100 % 10
千位:数值 /1000 % 10
\end{lstlisting}
\section{隐式转换与强制转换}
\subsection{两种转换}
数字相加时,数据类型不一样的,不能直接运算,需要转换成一样的,才能进行运算.
\begin{enumerate}
	\item {\color{red}\zihao{3}\textbf{隐式转换(不会产生程序错误)}}:把一个\textbf{取值范围小}的,转换成一个\textbf{取值范围大}的.
	\begin{enumerate}
		\item 如果两个不同类型的数据相加,比特位小的会转化为比特位大的数据.(\verb|double| > \verb|float| > \verb|long long| > \verb|long| > \verb|int| > \verb|short| > \verb|char|)
		\begin{figure}[H]
			\centering
			\includegraphics[width=0.7\linewidth]{隐式转换的第一种条件}
			\caption{隐式转换的第一种规则}
			\label{fig:16}
		\end{figure}
		\item \verb|char|与\verb|short|数据在进行运算时,会先转化为\verb|int|型数据.再进行运算.
		\begin{figure}[H]
			\centering
			\includegraphics[width=0.7\linewidth]{隐式转换第二种规则}
			\caption{隐式转换的第二种规则}
			\label{fig:17}
		\end{figure}
	\end{enumerate}
	\item {\color{red}\zihao{3}\textbf{强制转换}}:把一个\textbf{取值范围大}的,转换成一个\textbf{取值范围小}的.(原理,如:\verb|int|类型($1000 0000 0000 0000$)变成\verb|short|类型)前八位就要删掉$\cancel{1000 0000} 0000 0000$结果就会出错.
	\begin{enumerate}
		\item 格式{\color{red}\verb|目标数据类型 变量名=(目标数据类型)被强制转换的数据|}
\begin{lstlisting}[language=C, caption=C语言中强制转换格式, label=C.9]
	int b =12344;
	short i =(short)b;
\end{lstlisting}
\begin{figure}[H]
	\centering
	\includegraphics[width=0.7\linewidth]{强制转换格式}
	\caption{强制转换格式}
	\label{fig:18}
\end{figure}
	\end{enumerate}
\end{enumerate}
\subsection{字符相加}
由于键盘上的字符与\textit{\textbf{ASCLL码表}}具有一一对应关系,所以在运算时,键盘上的字符会先转化成\textit{\textbf{ASCLL码表}}上的数字一一对应的关系.
\begin{figure}[H]
	\centering
	\includegraphics[width=0.7\linewidth]{字符类型的运算}
	\caption{字符类型的运算}
	\label{fig:19}
\end{figure}
\section{自增自减运算符}
\begin{table}[H]
	\centering
	\begin{tabular}{|c|c|}
		\hline
		\multicolumn{2}{|c|}{自增自减运算符}\\
		\hline
		符号&说明\\
		\hline
		\verb|++|&变量中的值加1\\
		\hline
		\verb|--|&变量中的值减1\\
		\hline
	\end{tabular}
\end{table}
\begin{enumerate}
	\item 自增自减在window系统运行时规则
	\begin{enumerate}
		\item 前缀优先于后缀(++a优先于a++)
		\item 前缀统一自增/自减,再把结果拿出来用如
		\begin{lstlisting}[language=C, caption=在window系统中C语言中同时有前缀运算方法, label=C.10]
	int i = 1;
	++i + ++i = 3 + 3=6
		\end{lstlisting}
		\item 后缀统一先用,等整个表达式变量用完了,再进行自增或者自减
		\begin{lstlisting}[language=C, caption=在window系统中C语言中同时有后缀运算方法, label=C.11]
	int i = 1;
	i++ + i++ = 1 + 1=2
	i =3
		\end{lstlisting}
	\end{enumerate}
	
	\item 自增自减在linux、mac系统运行时规则
	\begin{enumerate}
		\item 前缀后缀优先级相同
		\begin{lstlisting}[language=C, caption=在linu、mac系统中C语言中同时有前缀运算方法, label=C.12]
	int i = 1;
	++i + ++i = 2 + 3=5
		\end{lstlisting}
		\item 从左到右依次计算
		\item 每一个前缀和后缀都是一个独立的个体
	\end{enumerate}
\end{enumerate}
\section{赋值运算符}
\begin{table}[H]
	\centering
	\begin{tabular}{|c|c|c|}
		\hline
		\multicolumn{3}{|c|}{赋值运算符}\\
		\hline
		符号&说明&举例\\
		\hline
		\verb|=|&直接赋值&int a =10,将10赋值给a\\
		\hline
		\verb|+=|&加后赋值&a+=b,将a+b的值赋值给a\\
		\hline
		\verb|-=|&减后赋值&a-=b,将a-b的值赋值给a\\
		\hline
		\verb|*=|&乘后赋值&a*=b,将a$\times$b的值赋值给a\\
		\hline
		\verb|/=|&除后赋值&a/=b,将a$\div$b的商给a\\
		\hline
		\verb|%=|&取余赋值&a\%=b,将a$\div$b的余数给a\\
		\hline
	\end{tabular}
\end{table}

\section{关系运算符}
\begin{table}[H]
	\centering
	\begin{tabular}{|c|c|c|}
		\hline
		\multicolumn{3}{|c|}{关系运算符}\\
		\hline
		符号&说明&结果\\
		\hline
		\verb|==|&a==b 判断a是不是等于b&\\
		\cline{1-2}
		\verb|!=|&a==b 判断a是不是不等于b&\\
		\cline{1-2}
		\verb|>|&a>b 判断a是不是大于b&成立1(真)、不成立0(假)\\
		\cline{1-2}
		\verb|>=|&a>=b 判断a是不是大于等于b&\\
		\cline{1-2}
		\verb|<|&a<b 判断a是不是小于b&\\
		\cline{1-2}
		\verb|<=|&a<=b 判断a是不是小于等于b &\\
		\hline
	\end{tabular}
\end{table}
\section{逻辑运算符}
\begin{center}
	\color{red}\zihao{1}符合数学逻辑运算
\end{center}
\begin{table}[H]
	\centering
	\begin{tabular}{|c|c|c|}
		\hline
		\multicolumn{3}{|c|}{逻辑运算符}\\
		\hline
		符号&说明&结果\\
		\hline
		\verb|&&|&与(而且)&两边都为真,结果才为真(同时满足)\\
		\hline
		\verb||||&或(或者)&两边都为假,结果才为假(二选一)\\
		\hline
		\verb|!|&非(取反)&取反\\
		\hline
	\end{tabular}
\end{table}
在C语言中代码两个运算逻辑不能直接连接,需要借助逻辑符号连接.

为了保持C语言运行的效率,C语言运行时,具有短路效果,如下代码\ref{C.14}中
\begin{lstlisting}[language=C, caption=C语言中短路效果表现, label=C.14]
	int a = 1,b = 5;
	a > 10 && ++b
	printf("a=%d,b=%d\n",a,b);
	输出a = 1,b=5
\end{lstlisting}
原因就是在识别到a > 10为假,C程序则不会接着读取后面内容,直接就输出了,运行结果.
\section{三元运算符}
\begin{table}[H]
	\centering
	\begin{tabular}{|c|c|}
		\hline
		\multicolumn{2}{|c|}{三元运算符}\\
		\hline
		符号&说明\\
		\hline
		\verb|a > b ? a : b ;|&a和b进行比较,为真则输出a,为假则输出b\\
		\hline
	\end{tabular}
\end{table}
\begin{lstlisting}[language=C, caption=C语言中三元运算符的效果, label=C.15]
	int a, b;
	int k=a > =b ? a : b
	printf("%d",a > =b ? a : b);
	printf("%d",k);
	输出结果一样
\end{lstlisting}
\section{逗号运算符(分隔符)}
\begin{enumerate}
	\item 从左到右依次运算.
	\item 最后一个子表达式的结果是整个表达式式的结果.
	\item 优先级最低(永远是最后执行).
\end{enumerate}
\begin{lstlisting}[language=C, caption=C语言中逗号运算符的效果, label=C.16]
	int i;
	printf("%d",(i = 3, ++ i, i++, i+5 ));
	输出结果i=10
\end{lstlisting}
\section{运算符的优先级}
\begin{table}[H]
	\centering
	\begin{tabular}{|c|c|}
		\hline
		\multicolumn{2}{|c|}{运算符的优先级}\\
		\hline
		运算符&说明\\
		\hline
		\verb|()|&小括号\\
		\hline
		\multirow{3}{*}{++ -\,-}&自增、自减\\
		 &windows:先++优先于后++\\
		 &mac Linux从左到右依次计算\\
		\hline
		\verb|+ - ！|&正号、负号、逻辑非\\
		\hline
		\verb|* / %|&乘、除、取余\\
		\hline
		\verb|+ -|&加、减\\
		\hline
		\verb|> >= < <=|&关系运算符\\
		\hline
		\verb|== !=|&关系运算符\\
		\hline
		\verb|&&|&逻辑与\\
		\hline
		\verb||||&逻辑或\\
		\hline
		\verb|?:|&三元运算符\\
		\hline
		\verb|= *= /= %= += -=|&赋值运算符\\
		\hline
		\verb|,|&逗号运算符\\
		\hline
	\end{tabular}
\end{table}
\begin{center}
	\color{red}\zihao{1}运算符的优先级
\end{center}
\begin{enumerate}
	\item 小括号优先于所有
	\item 一元运算符号>二元运算符>三元运算符
	\item \&\&>||>赋值
\end{enumerate}
\begin{center}
	\color{red}\zihao{3}三元运算符嵌套型,如何快速判断
\end{center}
如果在三元运算符中再次嵌套三元运算符,则需要寻找“?”与“:”使代码分块儿,便于更好的观察,以至于更方便做题
如:
\begin{lstlisting}[language=C, caption=C语言中逗号运算符的效果, label=C.17.1,escapeinside={(*@}{@*)}]
int x = 10, y = 20, z = 30, h = 40, w = 50; 
int number = x > h ? z > w ? x > z ? x > y ? x : y : z : w : w > h ? (*@\newline@*) w : h;
printf("%d",number);
输出结果:50
\end{lstlisting}
\begin{lstlisting}[language=C, caption=C语言中逗号运算符的效果, label=C.17.2,escapeinside={(*@}{@*)}]
int x = 10, y = 20, z = 30, h = 40, w = 50; 
int number = x > h ? (z > w ? (x > z ? (x > y ? (x) : (y)) : (z)) :(*@\newline@*)(w)) : (w > h ? w : h);
printf("%d",number);
输出结果:50
\end{lstlisting}\par
三元运算符语句中由于(“{\color{red}:}” \, “{\color{red}?}”)在一起,才为一个完整的语句,因此遇到各种三元嵌套,理应快速找到(“{\color{red}:}”\,“{\color{red}?}”)进行判断.解题关键：从左边儿第一个问号(“{\color{red}?}”),开始像右边儿找冒号(“{\color{red}:}”),如果该过程中,遇到了其他问号(“{\color{red}?}”),则需要找的冒号(“{\color{red}:}”)数量加1.
\begin{center}
	\color{red}\zihao{3}各种运算符嵌套型,如何快速判断
\end{center}
运算符优先级表中,自上而下,逐次寻找,并且与逻辑运算符短路效果不冲突.
如代码\ref{C.18}
\begin{lstlisting}[language=C, caption=C语言中逗号运算符的效果, label=C.18,escapeinside={(*@}{@*)}]
	int a = 3, b = 4, c = 5;
	printf("%d\n", a && b);//1
	printf("%d\n", a <= 5);//1
	printf("%d\n", a || b + c && b - c);//1
	printf("%d\n", !((a < b) && !c || 1));//0
\end{lstlisting}\par
第二行中可以把a = 3和b = 4均看成a = 3为真,b = 4为真,结果输出为1.\par
第四行中a为真首先就成立,于是又由于或逻辑的短路效果,后面就不用看,直接运算为1.\par
第五行中,首先就遵循,运算符优先级,先算最里面的括号(a < b)得1,
然后!c运算得0,于是1\&\&0得0,0||1得1,又因为!1为0,所以最后输出为0.
\chapter{流程运算语句({\color{red}\texttt{if判断语句}}与{\color{red}\texttt{初阶循环语句}})}
流程运算语句:通过一些语句,控制程序的执行流程.\newline 
大致分为分为三种
\begin{itemize}
	\item 顺序结构:从上往下依次执行,是程序默认的执行过程.
	\item 分支结构:程序在执行中出现了岔路.
	\begin{enumerate}
	\item {\color{red}\verb|if|}语句
	\item {\color{red}\verb|switch|}语句
	\end{enumerate}
	\item 循环结构:重复的执行某件事.
	\begin{enumerate}
	\item {\color{red}\verb|for|}循环
	\item {\color{red}\verb|while|}循环
	\item {\color{red}\verb|do…while|}循环
	\end{enumerate}
\end{itemize}
\section{变量的作用域与生命周期}
此章节建议把本章{\color{red}\verb|for|}循环学习完毕后,再进行阅读,效果会更佳.
\subsection{变量的作用域}
假如有个变量这个变量能在哪里使用，哪里就称之为这个变量的作用域，一租{\color{red}\verb|{ }|}就是一个作用域的两个边界里面的变量不会影响外面的代码。
\section{变量的生命周期}
	\begin{figure}[H]
		\begin{minipage}[t]{0.48\textwidth}%t表示与文本对齐
			\centering
			\includegraphics[width=1\textwidth]{C语言中变量生命周期1}
			\caption{C语言中变量生命周期1}
		\end{minipage}
		\begin{minipage}[t]{0.48\textwidth}%t表示与文本对齐
			\centering
			\includegraphics[width=1\textwidth]{C语言中变量生命周期2}
			\caption{C语言中变量生命周期2}
		\end{minipage}
		\begin{minipage}[t]{0.48\textwidth}%t表示与文本对齐
			\centering
			\includegraphics[width=1\textwidth]{C语言中变量生命周期3}
			\caption{C语言中变量生命周期3}
		\end{minipage}
		\label{fig.sz}
	\end{figure}
如图\ref{fig.sz}中
\begin{enumerate}
	\item 第一张图中课可见,把变量{\color{cyan}\verb|sum|}定义在了{\color{red}\verb|for|}循环大括号之外,由此可见最后输出是每一次循环的求和值.
	\item 第二张图中课可见,把变量{\color{cyan}\verb|sum|}定义在了{\color{red}\verb|for|}循环大括号之内,由此可见最后输出是每一次循环的i的值,因为{\color{cyan}\verb|sum = 0|},所以每次循环就是\verb|0 + 1|、\verb|0 + 1 + 1|……
	\item 第三张图中课可见,把变量{\color{cyan}\verb|sum|}定义在{\color{red}\verb|for|}循环里面和外面都有,最后内部的\newline {\color{blue}\verb|printf("%d\n", sum);|}输出为内部的{\color{cyan}\verb|sum|}的每次求和值；而内部的{\color{blue}\verb|printf("%d\n", sum);|}输出为外部的{\color{cyan}\verb|sum|}的最开始的赋值.
\end{enumerate}

由此可见,在大括号里面的定义只会在大括号里面有效,这就称之为变量的生命周期. 
\begin{enumerate}
	\item 全局变量的生命周期:整个程序的生命周期
	\item 局部变量的生命周期:进入作用域生命周期开始，出作用域生命周期结束。
\end{enumerate}
\section{顺序结构}
\begin{figure}[H]
	\centering
	\includegraphics[width=0.6\textwidth]{顺序结构的理解图.png}
	\caption{顺序结构的理解}
	\label{fig.20}
\end{figure}
如图\ref{fig.20}中,代码逐行运行,一直到{\color{red}\verb|scanf("%d",&a)|}时,若不输入a的值则无法运行下一行,如果输入数字,则再次运行出程序的结果.
\section{{\color{red}{}\texttt{if}}的三种使用方法}
\begin{enumerate}
	\item 在C语言中,如果判断的结果是一个数字,非0表示条件成立,0表示条件不成立.
	\begin{figure}[H]
		\begin{minipage}[t]{0.3\textwidth}%t表示与文本对齐
			\centering
			\includegraphics[width=1\textwidth]{if语句的真输出}
			\caption{if语句的真输出}
		\end{minipage}
		\begin{minipage}[t]{0.3\textwidth}%t表示与文本对齐
			\centering
			\includegraphics[width=1\textwidth]{if语句的负真输出}
			\caption{if语句的负真输出}
		\end{minipage}
		\begin{minipage}[t]{0.3\textwidth}%t表示与文本对齐
			\centering
			\includegraphics[width=1\textwidth]{if语句的假输出}
			\caption{if语句的假输出}
		\end{minipage}
		\label{fig.21}
	\end{figure}
	\item 在C语言中如果只有一个语句体,可以省略掉{\color{red}\verb|\{\}|}.
	\begin{figure}[H]
		\centering
		\includegraphics[width=0.7\linewidth]{if语句省略大括号}
		\caption{if语句省略大括号}
		\label{fig:22}
	\end{figure}
\end{enumerate}
\verb|if|语句是C语言中的分支语句,具有如下大致三种使用方法:
\subsection{{\color{red}{}\texttt{if}}第一种使用方法(对一种条件判断)}
%\begin{tikzpicture}[node distance=10pt]
%	\node[draw, rounded corners]                        (start)   {Start};
%	\node[draw, below=of start]                         (step 1)  {Step 1};
%	\node[draw, below=of step 1]                        (step 2)  {Step 2};
%	\node[draw, diamond, aspect=2, below=of step 2]     (choice)  {Choice};
%	\node[draw, right=30pt of choice]                   (step x)  {Step X};
%	\node[draw, rounded corners, below=20pt of choice]  (end)     {End};
%	\draw[->] (start)  -- (step 1);
%	\draw[->] (step 1) -- (step 2);
%	\draw[->] (step 2) -- (choice);
%	\draw[->] (choice) -- node[left]  {Yes} (end);
%	\draw[->] (choice) -- node[above] {No}  (step x);
%	\draw[->] (step x) -- (step x|-step 2) -> (step 2);
%\end{tikzpicture}
{\color{red}\begin{lstlisting}[language=C, caption=C语言中if的第一种使用格式, label=C.19]
	if(关系表达式)
	{
		语句体A
	}
\end{lstlisting}}

{\color{red}\verb|if|}可以理解为如果,代码可以理解为如果{\color{red}\verb|(关系表达式)|}里面的东西成立,则运行{\color{red}\verb|({语句体A})|}里面的东西,如果{\color{red}\verb|(关系表达式)|}里面的东西不成立,直接跳过{\color{red}\verb|\{\}|}运行其他代码.
\subsection{{\color{red}{}\texttt{if}}第二种使用方法(对两种条件判断)}
{\color{red}\begin{lstlisting}[language=C, caption=C语言中if的第二种使用格式, label=C.20]
	if(关系表达式)
	{
		语句体A;
	}
	else
	{
		语句体B;
	}
\end{lstlisting}}

{\color{red}\verb|if|}可以理解为如果,代码可以理解为如果{\color{red}\verb|(关系表达式)|}里面的东西成立,则运行{\color{red}\verb|({语句体A})|}里面的东西,如果{\color{red}\verb|(关系表达式)|}里面的东西不成立,直接跳过{\color{red}\verb|if|}后面的{\color{red}\verb|\{\}|}中的代码,运行其他{\color{red}\verb|else|}中的代码.
\subsection{{\color{red}{}\texttt{if}}第三种使用方法(对多种条件判断)}
{\color{red}\begin{lstlisting}[language=C, caption=C语言中if的第三种使用格式, label=C.21]
	if(关系表达式A)
	{
		语句体A;
	}
	else if (关系表达式B)
	{
		语句体B;
	}
		else if (关系表达式C)
	{
		语句体C;
	}
	……
	else
	{
		语句体N;
	}
\end{lstlisting}}

{\color{red}\verb|if|}可以理解为如果,代码可以理解为如果{\color{red}\verb|(关系表达式)|}里面的东西成立,则运行{\color{red}\verb|({语句体A})|}里面的东西,如果{\color{red}\verb|(关系表达式)|}里面的东西不成立,直接跳过{\color{red}\verb|if|}后面的{\color{red}\verb|\{\}|}中的代码,运行其他{\color{red}\verb|else if|}中的代码,如果不成立则再次跳过,知道运行到{\color{red}\verb|else|}代码.
\section{{\color{red}{}\texttt{switch}}语句}
{\color{red}\begin{lstlisting}[language=C, caption=C语言中switch的第三种使用格式, label=C.22]
	switch(表达式)
	{
	case 值1:
		语句体1;
		break;
	case 值2:
		语句体2;
		break;
	……
	default:
		语句体n;
		break;
	}
\end{lstlisting}}

{\color{red}\verb|switch|}可以理解为选择语句,后面{\color{red}\verb|(表达式)|}得出的值与后面{\color{red}\verb|case|}后的值对应上,则执行对应的语句,否则直接运行{\color{red}\verb|default|}后面的语句体.
\begin{center}
	\color{red}\zihao{3}\verb|switch|注意事项
\end{center}
\begin{enumerate}
	\item {\color{red}\verb|switch|}后面{\color{red}\verb|(表达式)|}内的表达式格式只能为{\color{red}整数}与{\color{red}字符}.
	\item {\color{red}\verb|case|}的值只能是{\color{red}整数}或者{\color{red}字符}的字面量,不能是变量.
	\item {\color{red}\verb|case|}值不允许重复.
	\item {\color{red}\verb|break|}表示中断、结束的意思,结束{\color{red}\verb|switch|}语句.
	\item {\color{red}\verb|default|}表示所有情况都不匹配就执行该处的内容.\newline 可以写在任何位置,甚至可以不写(若不写,则直接跳出该{\color{red}\verb|switch|}语句).
	\begin{figure}[H]
		\centering
		\includegraphics[width=0.7\linewidth]{default的位置不影响输出}
		\caption{default的位置不影响输出}
		\label{fig:23}
	\end{figure}
\end{enumerate}

\textbf{通常情况下都是用}{\color{red}\verb|if|}\textbf{语句第三种形式代替}{\color{red} \verb|switch| }\textbf{语句,但是}{\color{red} \verb|switch| }\textbf{语句执行效率更高,具体情况,具体分析.}

\textbf{原因是因为}{\color{red}\verb|if|}\textbf{语句一行一行的执行}{\color{red}\verb|else|}\textbf{判断,直到最后一个,}{\color{red}\verb|switch|}\textbf{语句,会直接选择定位数值存在的}{\color{red}\verb|case|}\textbf{直接执行该段代码.}
\section{{\color{red}{}\texttt{case}}穿透}
\begin{center}
	\color{red}\zihao{3}\verb|case|穿透的注意事项
\end{center}
\begin{enumerate}
	\item 根据{\color{red}\verb|switch()|}括号里面的数字,寻找匹配对应的{\color{red}\verb|case|}值
	\item 执行对应的{\color{red}\verb|case|}的值
	\item 如果在执行的过程中遇到了{\color{red}\verb|break|},那么直接结束整个{\color{red}\verb|switch|}\newline
	如果在执行中的过程没有遇到{\color{red}\verb|break|},那么就会继续执行下一个{\color{red}\verb|case|},直到遇到{\color{red}\verb|break|},或者把整个{\color{red}\verb|switch|}全部执行完,才会结束.
	\item {\color{red}\verb|case|}穿透只会往下穿,不会往上穿.
	\item 
\end{enumerate}
{\color{red}\begin{lstlisting}[language=C, caption=C语言中case穿透, label=C.23]
	switch(1)
	{
		case 值1:
			语句体1;
		case 值2:
			语句体2;
		case 值3:
			语句体3;
		default:
			语句体n;
		break;
	}
\end{lstlisting}}
\begin{figure}[H]
	\centering
	\includegraphics[width=0.7\linewidth]{C语言中case穿透效果}
	\caption{C语言中case穿透效果}
	\label{fig:24}
\end{figure}
\section{{\color{red}{}\texttt{for}}循环}
{\color{red}\begin{lstlisting}[language=C, caption=C语言中for循环, label=C.24]
	for(初始化语句;条件判断语句;条件控制语句)
	{
		(循环体语句)
	}
\end{lstlisting}}
\begin{figure}[H]
	\centering
	\includegraphics[width=0.7\linewidth]{for循环输出1到5}
	\caption{for循环输出1到5}
	\label{fig:25}
\end{figure}
\section{{\color{red}{}\texttt{for}}循环}
\begin{enumerate}
	\item 初始化语句:循环的{\color{red}开始条件}.
	\item 条件判断语句:循环的{\color{red}结束条件}.
	\item 条件控制语句:控制{\color{red}循环次数}的.
	\item 循环体语句:要{\color{red}重复执行}的代码.
\end{enumerate}
\begin{center}
	\color{red}\zihao{3}\verb|for|执行流程
\end{center}
\begin{enumerate}
	\item 进入{\color{red}\verb|for|}循环,执行初始化语句.
	\item 进入判断语句,看看判断是不是成立的.
	\begin{itemize}
		\item 成立,则继续执行循环体语句.
		\item 不成立,即结束此次循环.
	\end{itemize}
	\item 执行条件控制语句.
	\item 回到判断语句,继续执行.
	\item 执行完后,出{\color{red}\verb|\{\}|}继续往下执行程序.
\end{enumerate}
\section{{\color{red}{}\texttt{while}}循环}
{\color{red}\begin{lstlisting}[language=C, caption=C语言中while循环, label=C.25]
	初始化语句
	while(条件判断语句)
	{
		循环体语句
		条件控制语句
	}
\end{lstlisting}}
\begin{figure}[H]
	\centering
	\includegraphics[width=0.7\linewidth]{while循环输出1到5}
	\caption{while循环输出1到5}
	\label{fig:26}
\end{figure}
\section{{\color{red}{}\texttt{for}}循环}
\begin{center}
	\color{red}\zihao{3}\verb|while|执行流程
\end{center}
\begin{enumerate}
	\item 将{\color{red}\verb|初始化语句|}代入{\color{red}\verb|条件判断语句|}
	\item 进行循环,所要的循环内容.
	\item 再进入{\color{red}\verb|条件控制语句|}对条件形成新的要求.
	\begin{enumerate}
		\item 若成立则再次循环.
		\item 若不成立结束循环.
	\end{enumerate}
\end{enumerate}
\section{{\color{red}{}\texttt{for}}循环与{\color{red}{}\texttt{while}}循环比较}
\begin{enumerate}
	\item 语法成面上
	\begin{enumerate}
	\item {\color{red}\verb|for|}循环中,控制循环变量,因为归属{\color{red}\verb|for|}循环的语法结构中,在{\color{red}\verb|for|}循环结束后,就不能再次被访问到了.
	\item {\color{red}\verb|while|}循环中,控制循环变量,
	对于{\color{red}\verb|while|}循环来说不归属其语法结构中,在{\color{red}\verb|while|}循环结束后,该变量还可以继续使用.
	\end{enumerate}
	\item 使用习惯上
	\begin{enumerate}
		\item {\color{red}\verb|for|}:知道循环次数或者循环范围(如求一组数列的和(需要读取内容较小且知道次数时).
		\item {\color{red}\verb|while|}:不知道循环次数和范围,只知道循环结束的条件(如读取文件中的内容(需要读取内容庞大时)).
	\end{enumerate}
	\end{enumerate}
		{\color{red}\begin{lstlisting}[language=C, caption=C语言中for循环与while循环等价形式, label=C.26.1]
	int i = 1;
	for(;i <= 100; i++)
	{
		printf("%d\n",i);
	}	
	\end{lstlisting}}
	{\color{red}\begin{lstlisting}[language=C, caption=C语言中for循环与while循环等价形式, label=C.26.2]
	int i = 1;
	while(i <=100)
	{
		printf("%d\n",i++);
		i++ ;
	}
	\end{lstlisting}}

{\color{red}\verb|for|}循环将初始化语句写到外面如代码\ref{C.26.1}可得出与代码\ref{C.26.2}一样的效果.
\section{{\color{red}{}\texttt{do…while}}循环}

在{\color{red}\verb|do……while|}循环中,不管是否循环成立,都会先把循环里面的语句先执行一遍.
{\color{red}\begin{lstlisting}[language=C, caption=C语言中do…while循环, label=C.27]
	初始化语句;
	do{
		循环体语句;
		条件控制语句;
	}while(条件判断语句);
\end{lstlisting}}
\begin{figure}[H]
	\centering
	\includegraphics[width=0.7\linewidth]{do_while循环输出1到5}
	\caption{do……while循环输出1到5}
	\label{fig:27}
\end{figure}

\begin{center}
	\color{red}\zihao{3}\verb|do……while|执行流程
\end{center}
\begin{enumerate}
	\item 进入{\color{red}\verb|do……while|循环}.
	\item 先执行{\color{red}\verb|初始化语句|}.
	\item 进入{\color{red}\verb|\{\}|}执行{\color{red}\verb|循环体语句|}和{\color{red}\verb|条件控制语句|}.
	\item 再进入{\color{red}\verb|while|}进行条件判断
	\begin{enumerate}
		\item 如果结果{\color{red}\verb|条件判断语句|}成立,则回到{\color{red}\verb|循环体语句|}.
		\item 如果结果{\color{red}\verb|条件判断语句|}不成立,则直接跳出循环.
	\end{enumerate}
\end{enumerate}
\section{学完基础循环需要知道的一些知识}
\begin{enumerate}
	\item 在计算机运算中,不存在任何的乘除法,都是由加减法的简写如：\[3*2=2+2+2\mbox{\textit{或者}}3+3\]或者\[11/3=11-3-3-3\dots2\]
\end{enumerate}
\chapter{循环高级使用}
\begin{enumerate}
	\item 无限循环:永远停不下来
	\item 跳转控制语句:在巡皇过程中,跳转到其他语句上执行
	\item 循环嵌套:循环里面还有其他循环
\end{enumerate}
\section{无限循环}
\begin{center}
	\color{red}\zihao{3}三种无限循环
\end{center}
	\begin{figure}[H]
	\begin{minipage}[H]{0.6\textwidth}%t表示与文本对齐
		\centering
		\includegraphics[width=1\textwidth]{for无限循环}
		\caption{for无限循环}
	\end{minipage}
	\begin{minipage}[H]{0.6\textwidth}%t表示与文本对齐
		\centering
		\includegraphics[width=1\textwidth]{while无限循环}
		\caption{while无限循环}
	\end{minipage}
	\begin{minipage}[H]{0.6\textwidth}%t表示与文本对齐
		\centering
		\includegraphics[width=1\textwidth]{do……while无限循环}
		\caption{do……while无限循环}
	\end{minipage}
	\label{fig.28}
\end{figure}

其中第二种{\color{red}\verb|while|无限循环}用的最多,并且在命令窗中输入{\color{red}\verb|Ctrl+C|}即可停止运行.
\begin{center}
	\color{red}\zihao{3}无限循环注意点
\end{center}

由于无限循环永远停不下来,所以循环下面的代码不会执行.
\section{跳转控制语句{\color{red}{}\texttt{break}}与{\color{red}{}\texttt{continue}}}
\begin{center}
	\color{red}\zihao{3}break在循环中用法
\end{center}
\begin{figure}[H]
	\begin{minipage}[t]{0.6\textwidth}%t表示与文本对齐
		\centering
		\includegraphics[width=1\textwidth]{break再循环中的作用}
		\caption{break在循环中的作用(有break)}
	\end{minipage}
	\begin{minipage}[t]{0.6\textwidth}%t表示与文本对齐
		\centering
		\includegraphics[width=1\textwidth]{break再循环中的作用(无break)}
		\caption{break在循环中的作用(无break)}
	\end{minipage}
	\label{fig.29}
\end{figure}
\begin{center}
	\color{red}\zihao{3}continue在循环中用法
\end{center}
\begin{figure}[H]
	\begin{minipage}[t]{0.6\textwidth}%t表示与文本对齐
		\centering
		\includegraphics[width=1\textwidth]{continuecontinue在循环中的作用}
		\caption{continue在循环中的作用(有continue)}
	\end{minipage}
	\begin{minipage}[t]{0.6\textwidth}%t表示与文本对齐
		\centering
		\includegraphics[width=1\textwidth]{continue在循环中的作用(无continue)}
		\caption{continue在循环中的作用(无continue)}
	\end{minipage}
	\label{fig.30}
\end{figure}
\begin{enumerate}
	\item {\color{red}\verb|break|}只能写在{\color{red}\verb|switch|}或者循环语句中,表示结束整个语句.
	\item {\color{red}\verb|continue|}只能写在循环语句中,表示跳过本次循环,继续执行下次循环.
\end{enumerate}
\section{循环嵌套}
\subsection{打印矩形}

如程序\ref{C.28}中,首先就将每打8个$\ast$打印成出来,紧接着又换行,再就是外嵌循环一共循环7次.
{\color{red}\begin{lstlisting}[language=C, caption=循环打印矩形, label=C.28]
		for (int i = 1; i <= 7; i++) 
	{
		for (int j = 1; j <= 8; j++)
		{
			printf("*");
		}
		printf("\n");
	}
\end{lstlisting}}
\subsection{打印三角形}

在代码\ref{C.26.1}与代码\ref{C.26.2}中,要首先分析打印范围中每一行打印个数,如在代码\ref{C.26.1}中首先就要在内循环中将内部$\ast$每行打印个数以及循环次数做考虑.
{\color{red}\begin{lstlisting}[language=C, caption=循环打印正三角形, label=C.29.1]
	for (int i = 1; i <= 5; i++) 
	{
		for (int j = i; j <= 5; j++)
		{
			printf("*");
		}
		printf("\n");
	}
\end{lstlisting}}
{\color{red}\begin{lstlisting}[language=C, caption=循环打印反三角形, label=C.29.2]
		for (int i = 1; i <= 5; i++) 
		{
			for (int j = 1; j <= i; j++)
			{
				printf("*");
			}
			printf("\n");
		}
\end{lstlisting}}
\subsection{九九乘法表({\color{red}\texttt{$\backslash$t}}制表符)}
\begin{figure}[H]
	\centering
	\includegraphics[width=0.7\linewidth]{九九乘法表}
	\caption{九九乘法表}
	\label{fig:31}
\end{figure}

此九九乘法表本质上就是倒三角.
\begin{center}
	\color{red}\zihao{3}\verb|\t|在循环中用法
\end{center}

这里需要补充的一个知识点儿:{\color{red}\verb|\t|}表示为长度可变的大空格,键盘上是{\color{red}\verb|Tab|}键,称之为制表符,作用是打印图表之类的可以让这些图表对齐.

{\color{red}\verb|\t|}会根据前面的字母的个数在后面补空格,让整体的长度达到8或者8的倍数,最少补1个,最多补8个.
\begin{enumerate}
	\item \verb|abc\t|\ 补8个
	\item \verb|zhangsan\t|\ 补5个
	\item \verb|张\t|\ 补2个
\end{enumerate}
\subsection{计算质数}
\begin{figure}[H]
	\begin{minipage}[t]{0.6\textwidth}%t表示与文本对齐
		\centering
		\includegraphics[height=0.256\textheight]{求范围内质数代码}
		\caption{求范围内质数代码}
	\end{minipage}
	\begin{minipage}[t]{0.6\textwidth}%t表示与文本对齐
		\centering
		\includegraphics[height=0.256\textheight]{求范围内质数命令端}
		\caption{求范围内质数命令端出}
	\end{minipage}
	\label{fig.32}
\end{figure}
\begin{figure}[H]
	\centering
	\includegraphics[width=0.7\linewidth]{求所有质数代码}
	\caption{求所有质数代码}
	\label{fig:33}
\end{figure}
\subsection{求斐波那契数列}
\begin{figure}[H]
	\begin{minipage}[t]{0.6\textwidth}%t表示与文本对齐
		\centering%居中排列
		\includegraphics[width=1\textwidth]{斐波那契数列命令}%寻找这张图片
		\caption{斐波那契数列命令}%该图片在文中的名字
	\end{minipage}
	\begin{minipage}[t]{0.6\textwidth}%t表示与文本对齐
		\centering
		\includegraphics[height=0.256\textheight]{斐波那契数列输出}
		\caption{斐波那契数列输出}
	\end{minipage}
	\label{fig.33}%编号
\end{figure}
\subsection{求每个位制上的数和为15的数有哪些}
对于这种程序，需要掌握函数，会变得更加的高效，否则，就会相对的很困难。
\begin{figure}[H]
	\centering
	\includegraphics[width=0.7\linewidth]{求每个位制上的数和为15的数有哪些}
	\caption{求每个位制上的数和为15的数有哪些}
	\label{fig:34}
\end{figure}
\section{{\color{red}{}\texttt{goto}}跳出多层循环}
\begin{figure}[H]
	\begin{minipage}[t]{0.6\textwidth}
		\centering
		\includegraphics[width=1\textwidth]{正常的嵌套循环}
		\caption{正常的嵌套循环}
	\end{minipage}
	\begin{minipage}[t]{0.6\textwidth}
		\centering
		\includegraphics[width=1\textwidth]{break跳出内循环}
		\caption{break跳出内循环}
	\end{minipage}
	\begin{minipage}[t]{0.6\textwidth}
		\centering
		\includegraphics[width=1\textwidth]{goto跳出外循环}
		\caption{goto跳出外循环}
	\end{minipage}
	\label{fig.35}
\end{figure}
{\color{red}\verb|goto|}这是个跳转语句,可以用到任何地方,需要跳转到一个编号处,使用格式如代码\ref{C.30}
{\color{red}\begin{lstlisting}[language=C, caption=goto跳转关键字, label=C.30]
	for (int i = 1; i <= 5; i++) 
	{
		for (int j = 1; j <= i; j++)
		{
			printf("*");
			goto a;
		}
		printf("\n");
	}
		a: printf("跳转上面goto下面所有直到a:后面的语句")
\end{lstlisting}}
\chapter{函数}
\begin{center}
	\color{red}{\zihao{2}函数:}{\zihao{3}程序当中独立的功能}
\end{center}

人话：就是把重复的功能打包,让程序书写效率更好.
\section{函数的定义}

	定义函数通常是为了:
\begin{enumerate}
	\item 定义函数是为了干什么事情？{\color{red}函数体}
	\item 我干这件事儿需要什么才能完成？{\color{red}形参}
	\item 干完了之后,调用处是不是需要继续使用{\color{red}返回值类型},若不需要返回则使用{\color{red}\verb|void|}
\end{enumerate}
{\color{red}\begin{lstlisting}[language=C, caption=C语言函数书写格式, label=C.31]
	返回值类型 函数名(形参1,形参2……)
	{
		函数体;
		return 返回值;
	}
\end{lstlisting}}
{\color{red}\begin{lstlisting}[language=C, caption=C语言函数书写格式, label=C.31.1]
	int sum(int num1, num2)
	{
		int sum =num1 + num2;
		return sum;
	}
\end{lstlisting}}
\begin{center}
	\color{red}{\zihao{2}函数定义:}{\zihao{3}函数结构各个部分功能}
\end{center}
\begin{enumerate}
	\item 返回值类型:就是这个函数的类型.
	\item 函数名:就是这个函数整体的名字,最后不管是调用还是调出结果,用这个缩写,更方便使用.
	\item 函数体:就是这个函数的内容.
	\item 返回值{\color{red}\verb|return 返回值|}
	\begin{enumerate}
		\item 结束这个函数.
		\item 使这个函数可以调用.
		\item 返回值类型就是看这个函数最后输出的类型是什么,假如是浮点型那么就是{\color{red}{\verb|double|}}之类.
	\end{enumerate}
\end{enumerate}
\section{函数的使用}
\begin{enumerate}
	\item 在代码中直接用:\newline 使用方式为直接写{\color{red}{\verb|函数名();|}}
	\begin{figure}[H]
		\centering
		\includegraphics[width=0.7\linewidth]{函数的求和调用}
		\caption{函数的求和调用}
		\label{fig:36}
	\end{figure}
	\item 在代码中有参数的求和调用:\newline
	\begin{figure}[H]
		\centering
		\includegraphics[width=0.7\linewidth]{不明确参数定义方法}
		\caption{不明确参数定义方法}
		\label{fig:37}
	\end{figure}
	{\color{red}\begin{lstlisting}[language=C, caption=C语言函数的输入量书写格式, label=C.32]
	void 函数名(形参1,形参2,……)
	{
		函数体;
	}
	
	int main()
	{
		函数名(实参1,实参2,……);
	}
	\end{lstlisting}}
\begin{center}
	{\color{red}\zihao{2}函数的注意事项:}	
\end{center}
\begin{enumerate}
	\item 函数不调用就不执行
	\item 函数名不能重复
	\item 函数和函数之间是平级关系,不能嵌套定义
	\item 自定义函数写在{\color{red}\verb|main|}函数下面,需要在上方申明
	\item {\color{red}\verb|return|}下面,不能编写代码,永远执行不到,属于无效代码.
	\item 函数的返回值类型为{\color{red}\verb|void|},表示没有返回值,{\color{red}\verb|return|}可以省略不写,如果写了{\color{red}\verb|return|},后面不能跟具体的数据,仅表示结束函数.
	\item \verb|实参|与\verb|形参|必须一一对应
\end{enumerate}
\end{enumerate}
\section{常见的函数}
\subsection{{\color{red}{}\texttt{math}}(数学库)头文件}

就是一些数学的常用算术,算法,比如,幂运算,对数运算,三角运算之类的,如图\ref{fig:38}
	\begin{figure}[H]
	\centering
	\includegraphics[width=0.7\linewidth]{C语言中的数学库}
	\caption{C语言中的数学库}
	\label{fig:38}
\end{figure}
\subsection{{\color{red}{}\texttt{time}}(时间库)头文件}
\begin{enumerate}
	\item {\color{red}{\verb|time()|}}函数,为什么要用{\color{red}{\verb|long long|}}类型的返回值,\newline 在图\ref{fig:39}1中按住{\color{red}{\verb|Ctrl+鼠标左击|}}点击{\color{red}{\verb|time(NULL)|}},然后进入图2中,按住{\color{red}{\verb|Ctrl+鼠标左击|}}点击{\color{red}{\verb|time_t|}},然后进入图3,按住{\color{red}{\verb|Ctrl+鼠标左击|}}点击{\color{red}{\verb|__time64_t|}},最后进入图4,于是就可以查看{\color{red}{\verb|time()|}}所占位数为{\color{red}{\verb|__int64|}}.
\begin{figure}[H]
	\centering
	\includegraphics[width=0.7\linewidth]{time函数查询格式}
	\caption{time函数查询格式}
	\label{fig:39}
\end{figure}
\item {\color{red}{\verb|time(NULL)|}}其中括号里面的参数表示获取当前的时间是否需要在其他地方进行储存,其中{\color{red}{\verb|NULL|}}表示,不需要在其他地方进行储存.
\end{enumerate}
\subsection{{\color{red}{}\texttt{stdlid}}(标准库)头文件}
这个标准库全称为{\color{red}\verb|standard library|}
{\color{red}\begin{lstlisting}[language=C, caption=C语言随机数使用格式, label=C.33]
#include <stdio.h>
#include <stdlib.h>//C语言的标准库,调用随机数函数

int main()
{
	srand(1);//设置种子
	int a = rand();//设置随机数
	printf("%d\n", a);//输出打印
	return 0;
}
\end{lstlisting}}
C语言中的随机数实际上是伪随机数,就是利用数学上的线性同余方程公式计算而来:
\[x_{n+1}=(ax_{n}+b)\ mod\ m\]
其中参数可以决定随机数的范围和均匀度,如：$x_{n+1}$表示当前要计算的那个随机数,$x_{n}$表示前一个数,$mod$表示获取余数.\newline 使用{\color{red}{\verb|srand(种子)|}}设置种子\newline 使用{\color{red}{\verb|rand()|}}获取随机数
\begin{figure}[H]
	\begin{minipage}[t]{0.6\textwidth}%t表示与文本对齐
		\centering%居中排列
		\includegraphics[width=1\textwidth]{单次输出随机数}%寻找这张图片
		\caption{单次输出随机数}%该图片在文中的名字
	\end{minipage}
	\begin{minipage}[t]{0.6\textwidth}%t表示与文本对齐
		\centering
		\includegraphics[height=0.228\textheight]{多次输出随机数}
		\caption{多次输出随机数}
	\end{minipage}
	\label{fig.40}%编号
\end{figure}
\subsubsection{随机数需要解决的两个小弊端}
\begin{enumerate}
	\item 种子不变,随机数结果是固定的:\newline 解决方案:
	因为时间是一直变化的所以我们要引入时间库,写在{\color{red}{\verb|srand()|}}的括号里面于是可以得到{\color{red}{\verb|srand(time(NULL))|}}就可以得到更随机的伪随机数.
	{\color{red}\begin{lstlisting}[language=C, caption=C语言当中更随机的伪随机数生成, label=C.34]
	#include <stdio.h>
	#include <stdlib.h>
	#include <time.h>
	
	int main() 
	{
		srand(time(NULL));
		for (int i = 1; i <= 10; i++) 
		{
			int a = rand();
			printf("%d\n", a);
		}
		return 0;
	}
	\end{lstlisting}}
	\item 随机数的范围(默认范围是0$\sim$32767)\newline 假如生成1--100的随机数.
	\begin{enumerate}
		\item 把这个范围变成包头不包尾,包左不包右1--101
		\item 拿着尾巴减开头$101 - 1= 100$
		\item 修改代码
	\end{enumerate}
	思路如下:代码\ref{C.35}中,变量a对100取余范围为0--99,再加上1范围就是1--100,这样子就可以达到控制范围的效果了.
	{\color{red}\begin{lstlisting}[language=C, caption=C语言当中能控制范围更随机的伪随机数生成, label=C.35]
int main() 
{
	srand(time(NULL));
	for (int i = 1; i <= 10; i++) 
	{
		int a = rand() % 100 + 1z;
		printf("%d\n", a);
	}
	return 0;
}
	\end{lstlisting}}
\end{enumerate}
\chapter{数组}
\section{数组的定义}
数组:是一种容器,可以用来存储同种数据类型的多个值.\newline
{\color{red}{\verb|数据类型 数组名[长度]|}}如{\color{red}{\verb|int arr [3]|}}
\begin{center}
	\color{red}\zihao{3}数组的特点
\end{center}
\begin{enumerate}
	\item 连续的空间
	\item 一旦定义，长度不可变
	\item 若这个数据本身的类型与数组的数据类型不一样时，这个数据就会发生隐式转换服从该数组
\end{enumerate}
\section{数组的初始化}
初始化:定义数组时,第一次给数组赋值.\newline
{\color{red}{\verb|数据类型 数组名[长度] = {数据值,数据值……}|}}如{\color{red}{\verb|int arr [3] = {1,2,3}|}}
\begin{center}
	\color{red}\zihao{3}数组初始化的细节
\end{center}
\begin{enumerate}
	\item \textbf{长度省略:}数据值的个数就是数组长度.\newline
	{\color{red}{\verb|int arr [] = {1,2,3}|}}虽然中括号中没写内容,但是这个数组有三个数据,所以该数组长度为3.
	\item \textbf{长度未省略:}数据值的个数小于等于数组长度.\newline 
	{\color{red}{\verb|int arr [5] = {1,2,3}|}}虽然长度为5但是只有3个数值,所以后面会补上默认值,\newline 整数型如下	{\color{red}{\verb|int arr [5] = {1,2,3,0,0}|}},\newline 浮点型如下	{\color{red}{\verb|double arr [5] = {1.2,2.2,3.2,0.0,0.0}|}},\newline 字符型如下	{\color{red}{\verb|char arr [5] = {'a','b','3','\0','\0'}|}}\newline 字符串会被{\color{red}\verb|NULL|}替代.
\end{enumerate}
\section{数组的元素访问}
无论是数组元素访问中的获取还是修改，都要引入一个\textbf{索引}的概念
\subsubsection{\color{red}索引}
在{\color{red}{\verb|int arr [5] = {1,2,3,4,5}|}}中,第几个数就是索引\newline 索引就是数组的一个编号，也叫做:角标、下表、编号.\newline 特点:从0开始连续加1,不间断.
\subsection{数组的中的元素获取}
如在此代码中{\color{red}{\verb|int arr [5] = {1,2,3,4,5}|}},\newline {\color{red}{\verb|变量 = 数组名[索引]|}}\ (\ {\color{red}{\verb|int a = arr[4] = 5|}}\ )\newline  再引入输出函数{\color{red}{\verb|printf("占位符",数组名[索引]|)}}\ (\  {\color{red}{\verb|printf("\%d",arr[4])|}}\ )\ 就是数组中的元素被获取的方式.
\subsection{数组的中的元素修改}
如在此代码中{\color{red}{\verb|int arr [5] = {1,2,3,4,5}|}},\newline {\color{red}{\verb|数组名[索引] = 数据值|}}\ (\ {\color{red}{\verb|arr[4] = 6|}}\ )就是数组元素的修改方式. 
\section{数组的遍历}
遍历:依次获取数组中的每一个元素.
\begin{figure}[H]
	\centering
	\includegraphics[width=0.7\linewidth]{数组的遍历}
	\caption{数组的遍历}
	\label{fig:41}
\end{figure}
数组的遍历就是用循环把数组中每个数都选中一次
\section{内存中的数组}
\subsection{内存是什么}
内存：软件在运行时，用来临时存储数据的。

数据并不是能立即保存到硬盘里面的，首先需要IO设备输入进内存中，随后才可以保存到硬盘，在保存的过程中，硬盘就需要寻找到这个内存所在的位置，为了更快找到，这个数据的位置，于是就有内存地址的出现了。
内存又分为32位和64位的

\subsection{什么是内存地址}
内存地址：便于把数据保存到内存中（以字节为单位），从内存对应位置，把数据提出来

内存地址就是为了让保存的数据更好的提出使用，而产生的，让数据的使用效率更好
\begin{enumerate}
	\item 32位的操作系统，内存以32位二进制表示：\\
	最小的地址0000 0000 0000 0000 0000 0000 0000 0000\\
	最大的地址1111 1111 1111 1111 1111 1111 1111 1111\\（为$2^{32}=42,9496,7296\text{字节}=419,4304(\mathrm{KB})=4096(\mathrm{MB})=4(\mathrm{GB})$）
	\item 64位的操作系统，内存以64位的二进制表示：\\
	最小的地址0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000\\
	最大的地址1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111\\（为$2^{64}=1844,6744,0737,0955,1616\text{字节}=18,014,398,509,481,984(\mathrm{KB})=17,592,186,044,416(\mathrm{MB})=17,592,186(\mathrm{GB}=17,179(\mathrm{TB})$）\\
	又由于64位的内存地址不太好阅读，所以我们会把每四个分成一组，换成16进制阅读，如\\64位的2进制：0000 0000 0000 0000 0001 0000 1111 1010 0000 0000 0010 0000 0000 0010 0000 1000转化成16位的16进制：0 0 0 0 1 0 F A 0 0 2 0 0 2 0 8
\end{enumerate}
\subsection{C语言中的内存地址查看}
在C语言当中，每一个数据类型所占用的内存个数是一样的，如{\color{red}\verb|int|}类型，无论在哪儿，都是占4个字节，这4个字节是连续不间断的，但是，这4个字节所在的内存位置都是随机的。

在代码\ref{C.36}里面，命令端所显示的地址都是这个{\color{red}\verb|int|}变量的首地址，{\color{red}\verb|int|}变量是不会把自己四个地址都显示出来的额，因为不够简便，但是显示首地址后，剩下的三个地址都是连续的。

{\color{red}\verb|&|}前文介绍过，这是取址符\\
{\color{red}\verb|%p|}这个p是Pointer（指针）的缩写，表示找到这个地址的指针
	{\color{red}\begin{lstlisting}[language=C, caption=C语言中的内存地址查看方法, label=C.36]
		#include <stdio.h>
		#include <stdio.h>
		
		int main() 
		{
			int a = 10;
			printf("%p\n",a);
			int b = 20;
			printf("%p\n",b);
			int c = 30;
			printf("%p\n",c);
		}
\end{lstlisting}}
\begin{figure}[H]
	\centering
	\includegraphics[width=0.5\linewidth]{C语言当中内存地址查看方法}
	\caption{C语言当中内存地址查看方法}
	\label{fig:42}
\end{figure}
\subsection{数组在内存中的储存方式}
如给定一个数组{\color{red}\verb|int arr[3]={1,2,3}|}，这个数组在内存中，整数1,2,3都是挨着排列的，地址都是相邻的，通常找到第一个地址，直接，我们索引+1，意为在内存中，后移4个字节长度({\color{red}\verb|int|}类型，长度为4个字节)。

我们找数组第一个索引的位置{\color{red}\verb|arr[0]=1|}在内存中给出一个地址，随后每次索引+1的地址都是字节
\begin{figure}[H]
	\centering
	\includegraphics[width=0.7\linewidth]{C语言当中数组内存的理解}
	\caption{C语言当中数组内存的理解}
	\label{fig:43}
\end{figure}
如图\ref{fig:43}中所示，{\color{red}\verb|int arr[3]={1,2,3}|}第一个数据地址就是6F8，第二个地址就加4了就成立6FC,第三个地址极速700，所以数组中的存储都挨着，然后每个都是类型的单位长度一直往后移动。
\subsubsection{通过变量的首地址，就可以确定变量中的存储的数据吗？}
根据首地址，只能知道{\color{red}第一个字节}中的数据，我们还要根据{\color{red}数据类型}才能知道当前的数据占多少个字节
\subsubsection{索引为什么是从0开始的？}
因为素组中第一个数据偏移量为0，后面的偏移量逐渐+1，字节数也随着数据类型逐渐增加。
\subsubsection{数组的长度如何计算？}
\[\text{数组长度}=\frac{\text{总长度}}{\text{数据类型占用字节个数}}\]
\section{数组的常见问题}
{\color{red}\begin{lstlisting}[language=C, caption=C语言数组的形参意义以及在主函数的意义, label=C.37]
#include <stdio.h>
int Arr(int arr[],int len)
{
	for (int i = 0; i < len; i++)
	{
		printf("这个数组第%d个数据%d\n", (i + 1), arr[i]);
	}
}
int main()
{
	int arr[] = { 1,2,3,4,5 };
	int len = sizeof(arr) / sizeof(int);
	Arr(arr,len);
	return 0;
}
\end{lstlisting}}
\subsection{数组作为函数的形参}
在代码\ref{C.37}中，数组作为形参传递时，传递的是数组首地址，后面的数就不会跟着传递。如果需要对函数中的数组进行遍历的话，那么一定要把数组的长度一起传递进去。\\
定义处的{\color{red}\verb|arr|}表示的是完整的数组。\\
函数处的{\color{red}\verb|arr|}只是一个变量，用来记录数组的首地址。\\
\subsection{数组索引的越界}
在代码\ref{C.37}中，若选中函数的{\color{red}\verb|	printf("这个数组第%d个数据%d\n", (i + 1));|}{\color{red}\verb|arr[i]|}的{\color{red}\verb|i|}超过了索引长度，则会出现一堆随机数
\section{数组的算法题}
\subsubsection{求最值}
{\color{red}\begin{lstlisting}[language=C, caption=C语言数组的求最值, label=C.38]
#include <stdio.h>

int main()
{
	int arr[] = { 33,5,22,44,55 };
	int len = sizeof(arr) / sizeof(int);
	int temp=arr[0];
	for (int i = 1; i < len;i++) 
	{
		if (temp<arr[i]) 
		{
			temp = arr[i];
		}
	}
	printf("%d\n",temp);
	for (int i = 1; i < len; i++)
	{
		if (temp > arr[i])
		{
			temp = arr[i];
		}
	}
	printf("%d\n", temp);
	return 0;
//输出：55
//输出：5
}
\end{lstlisting}}
\subsubsection{求和}
{\color{red}\begin{lstlisting}[language=C, caption=C语言数组的求和, label=C.39]
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <time.h>
#include <stdlib.h>

//判断numer在函数中是否重复
int Unequal(int arr[],int len,int number)
{
	for (int i = 0; i < len; i++)
	{
		if (arr[i]==number) 
		{
			return 1;
		}
	}
	return 0;
}

int main()
{
	//设置数组
	int arr[10] = { 0 };
	//设置储存变量
	int sum = 0;
	int j = 0;
	//设置随机数种子
	srand(time(NULL));
	//求这个数组长度
	int len = sizeof(arr) / sizeof(int);
	for (int i = 0; i < len; )
	{
		//限定一个随机数范围0~100的随机数
		int number = rand() % 100 + 1;
		//判断这十个随机数是不是相等的
		int temp = Unequal(arr, len, number);
		if (!temp) 
		{
			arr[i] = number;
			i++;
		}
	}
	for (int i = 0; i < len; i++)
	{
		//对这十个随机数求和
		printf("%d\n", arr[i]);
	}
	for (int i = 0; i < len; i++)
	{
		//对这十个随机数求和
		sum = sum + arr[i];
	}
	double average =((double)sum )/ len;
	printf("这个数组的和：%d\n",sum);
	printf("这个数组的平均值：%lf\n",average);
	for (int i = 0; i < len; i++) 
	{
		if (arr[i] < average)
		{
			j++;
		}
	}
	printf("这个数组中有%d个数据比平均值小", j);
	return 0;
}
\end{lstlisting}}
\subsubsection{反转数组}
{\color{red}\begin{lstlisting}[language=C, caption=C语言数组元素的反转, label=C.40]
#include <stdio.h>

int main()
{
	int arr[5];
	int len = sizeof(arr) / sizeof(int);
	for (int i = 0; i < len; i++) 
	{
		scanf("%d", &arr[i]);	
	}
	for (int i = 0; i < len; i++)
	{
		printf("%d\n", arr[i]);
	}
	for (int i = len; i > 0; i--)
	{
		printf("%d\n", arr[i-1]);
	}
	return 0;
}
\end{lstlisting}}
\subsubsection{打乱数据}
{\color{red}\begin{lstlisting}[language=C, caption=C语言数组元素的打乱, label=C.41]
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main()
{
	int arr[5] = {1,2,3,4,5};
	int len = sizeof(arr) / sizeof(int);
	srand(time(NULL));
	for (int i = 0; i < len; i++) 
	{
		int num1 = rand() % len;
		int temp = arr[i];
		arr[i] = arr[num1];
		arr[num1] = temp;
	}
	for (int i = 0; i < len; i++)
	{
		printf("%d\n",arr[i]);
	}
	return 0;
}
\end{lstlisting}}
\section{数组的一些常用小算法}
\subsection{基本查找\&顺序查找}
对数据没有要求，但是查询效率低。
{\color{red}\begin{lstlisting}[language=C, caption=C语言基本查找算法, label=C.42]
#include <stdio.h>

int Find(int arr[],int len,int num) 
{
	for (int i = 0; i < len; i++) 
	{
		if (num == arr[i])
		{
			return (i+1);
		}
	}
	return -1;
}

int main()
{
	int arr[] = {11,27,12,823,111,223,112,7219};
	int len = sizeof(arr) / sizeof(int);
	int num;
	scanf("%d",&num);
	if (Find(arr, len, num)!=-1) 
	{
		printf("是数组中第%d个数据", Find(arr, len, num));
	}
	else
	{
		printf("不是数组中的数据");
	}
	return 0;
}
\end{lstlisting}}
\subsection{二分查找}
前置条件：数组里面的数据必须是有序的
{\color{red}\begin{lstlisting}[language=C, caption=C语言二分查找算法, label=C.43]
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
//利用二分查找法，查找数据
int Dichotomy(int arr[],int len,int num)
{
	//确定查找范围
	int max = len - 1;
	int min = 0;
	while(min<=max)
	{
		int mid = (max+min)/2;
		//用arr[mid]和num比较
		if (arr[mid] < num)	
		{
			min = mid + 1;
			
		}
		else if (arr[mid] > num)
		{
			max = mid - 1;
		}
		else 
		{
			return mid+1;
		}
	}
	return -1;
}

int main()
{
	// 定义数组
	int arr[] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 };
	//计算数组长度
	int len = sizeof(arr) / sizeof(int);
	//输入需要查找的数据
	int num;
	scanf("%d", &num);
	printf("这个数组第%d个数据", Dichotomy(arr, len, num));
	return 0;
}	
\end{lstlisting}}
\subsubsection{二分查找的优势}
相较于基本的顺序查找，效率更快，因为每次只用找一半
\subsubsection{二分查找的优势？}
首先，这个数列必需是有序的，其次如果数据是乱的，先排序再利用二分查找的索引没有实际意义，只能确实当前数字在数组中是否存在，因为排序之后数字的位置可能变化了。
\subsubsection{二分查找的过程}
\begin{enumerate}
	\item 首先定义最大值{\color{red}\verb|max|}和最小值{\color{red}\verb|min|}表示当前要查找的范围
	\item {\color{red}\verb|mid|}是定义在{\color{red}\verb|min|}和{\color{red}\verb|max|}中间的
	\item 
	\begin{enumerate}
		\item 如果要查找的元素在{\color{red}\verb|mid|}左边，缩小范围时，{\color{red}\verb|min|}不变，{\color{red}\verb|max|}等于{\color{red}\verb|mid-1|}
		\item 如果要查找的元素在{\color{red}\verb|mid|}右边，缩小范围时，{\color{red}\verb|max|}不变，{\color{red}\verb|min|}等于{\color{red}\verb|mid+ 1|}
	\end{enumerate}
\end{enumerate}
\subsection{插值查找}
就是在二分查找基础上，将{\color{red}\verb|mid|}的值改为:\\{\color{red}\verb|mid=min+(key-arr[min])/(arr[max]-arr[max])*(max-min)|}即
\[\mathtt{mid}=\mathtt{min}+\frac{(\mathtt{key}-\mathtt{arr[min]})}{(\mathtt{arr[max]}-\mathtt{arr[min]})}\times(\mathtt{max}-\mathtt{min})\]
如此，若这个数组排列的更有序且更均匀，则比二分查找法更快速。
{\color{red}\begin{lstlisting}[language=C, caption=C语言插值查找, label=C.44]
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
//利用二分查找法，查找数据
int interpolation(int arr[],int len,int number)
{
	int min = 0;
	int max = len - 1;
	while (min < max)
	{
		{int mid = min + (number - arr[min]) /
		 (arr[max] - arr[min]) * (max - min);}
		if (arr[mid] < number)
		{
			min = mid + 1;
		}
		else if (arr[mid] > number)	
		{
			max = mid - 1;
		}
		else
		{
			return (mid + 1);
		}
	}
	return -1;
}

int main()
{
	int arr[] = {1,2,3,4,5,6,7,8,9};
	int len = sizeof(arr) / sizeof(int);
	int number;
	scanf("%d", &number);
	if (interpolation(arr, len, number) != -1)
	{
		printf("%d", interpolation(arr, len, number));
	}
	else
	{
		printf("该数组中没有这个元素");
	}
	return 0;
}
\end{lstlisting}}
\subsection{分块查找和哈希查找}
\begin{enumerate}
	\item 前一块儿中的最大数据小于后一块儿中所有数据，（块儿内无序，块是有序的）
	\item 块数数量一般等于数字的个数开根号，比如16个数字一般分4块儿
\end{enumerate}
{\color{red}\begin{lstlisting}[language=C, caption=C语言分块查找和哈希查找, label=C.45]
\end{lstlisting}}
\subsection{冒泡排序}
\begin{enumerate}
	\item 相邻元素两两比较，大的放在右边，小的放在左边
	\item 第一轮循环结束后，最大值已经找到，在数组最右边
	\item 第二轮循环只要在剩余的元素找最大值就可以了
	\item 第二轮结束后，次大值已经确定，第三轮循环继续在剩余数据中循环。
	\item 每一轮循环都会减少一次
	\item 若有n个数据则，只需要执行n-1次循环
\end{enumerate}
{\color{red}\begin{lstlisting}[language=C, caption=C语言冒泡排序, label=C.46]
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int ooo(int arr[], int len)
{
	for (int j = 0; j < len; j++) 
	{
		for (int i = 0; i < len - 1 - j; i++)
		{
			if (arr[i] > arr[i + 1])
			{
				int temp = arr[i];
				arr[i] = arr[i + 1];
				arr[i + 1] = temp;
			}
		}
		printf("%d\n", arr[j]);
	}
}
int main()
{
	int arr[] = { 79,81,127,131,7,23,103 };
	int len = sizeof(arr) / sizeof(int);
	ooo(arr, len);
	return 0;
}
\end{lstlisting}}
\subsection{选择排序}
\begin{enumerate}
	\item 从0索引开始，跟后面的元素一一比较
	\item 小的放前面，大的放后面
	\item 第一轮循环结束后，最小的数据已经确定
	\item 第二轮循环从1索引开始以此类推
\end{enumerate}
{\color{red}\begin{lstlisting}[language=C, caption=C语言选择排序, label=C.47]
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int Choose(int arr[],int len)
{
	for (int i = 0; i < len-1; i++)
	{
		for (int j = i + 1; j < len; j++) 
		{
			if (arr[i] > arr[j])
			{
				int temp = arr[i];
				arr[i] = arr[j];
				arr[j] = temp;
			}
		}
		printf("%d\n",arr[i]);
	}
}
int main()
{
	int arr[] = { 2,3,4,1,5,6,7,8,9 };
	int len = sizeof(arr) / sizeof(int);
	Choose(arr, len);
	return 0;
}
\end{lstlisting}}
\chapter{指针}
\section{指针是什么}
\subsection{指针的定义}
指针全称指针也就是内存地址。\\
指针变量存储的是内存地址。
\subsection{指针的格式}
{\color{red}\verb|数据类型*变量名=&变量;|}\\
{\color{red}\verb|数据类型|}需要和指向变量保持一致。\\
{\color{red}\verb|*|}表示标记变量名这个变量为指针变量,变量里面存储的是内存地址。\\
{\color{red}\verb|变量名|}自己给变量起的名字。
{\color{red}\begin{lstlisting}[language=C, caption=C语言指针变量的格式, label=C.48]
int a=10;
int* p=&a;
printf("%d",*p);
\end{lstlisting}}
此代码\ref{C.48}，表示在内存当中有个变量{\color{red}\verb|a=10|}，获取变量{\color{red}\verb|a|}的内存地址{\color{red}\verb|&a|}存储到指针{\color{red}\verb|p|}里面。
其中{\color{red}\verb|int* p=&a;|}里面的{\color{red}\verb|*|}是标记当前是一个指针，里面记录的内存地址，但是{\color{red}\verb|printf("%d",*p);|}里面的{\color{red}\verb|*|}是解引用运算符，通过后面的内存地址，获取得到的数据。
\subsection{查询数据和存储数据}
\subsubsection{查询数据和存储数据代码}
{\color{red}\begin{lstlisting}[language=C, caption=C语言指针的使用与修改变量, label=C.49]
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
	int a = 10;
	int* p = &a;
	printf("%d\n",*p);
	\\输出10
	*p = 100;
	printf("%d\n",a);
	\\输出100
	return 0;
}
\end{lstlisting}}
\subsubsection{查询数据和存储小细节}
\begin{enumerate}
	\item 指针变量的名字是{\color{red}\verb|p|}而不是{\color{red}\verb|*p|}
	\item 指针变量的数据类型要跟指向变量的类型保持一致
	\item 指针内存占用大小，跟数据类型无关，与编译器有关(32位的编译器占4字节，64位的编译器占8字节。)
	\item 给指针变量赋值时候不能直接给指针赋成一个确定的数值。
\end{enumerate}
\section{指针在C语言中的作用}
\subsection{操作其他函数中的变量}
传递变量的地址，一样可以改变变量的值。
\subsubsection{第一个作用的代码展示}
{\color{red}\begin{lstlisting}[language=C, caption=C语言指针的操作其他函数中的变量, label=C.50]
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int B(int* p1, int* p2)
{
	int temp = *p1;
	*p1 = *p2;
	*p2 = temp;
}

int main()
{
	int a = 10;
	int b = 20;
	int* p1 = &a;
	int* p2 = &b;
	printf("调用前a=%d,b=%d\n", a, b);
	B(&a, &b);
	printf("调用后a=%d,b=%d\n", a,b);
	return 0;
}
\end{lstlisting}}
\subsection{第一个作用的小细节}
函数中变量的生命周期跟函数有关，函数结束后，变量也会消失，此时在其他函数中就无法使用指针了，如果不想函数中的变量被回收，可以在变量前面加上{\color{red}\verb|static|}(静态)字样
{\color{red}\begin{lstlisting}[language=C, caption=C语言指针周期会被破坏型, label=C.51.1]
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int* ppp()
{
	int a = 10;
	return &a;
}

int main()
{
	int* p = ppp();
	printf("%d\n",*p);
	printf("%d\n",*p);
	printf("%d\n",*p);
	printf("%d\n",*p);
	printf("%d\n",*p);
	return 0;
}
\end{lstlisting}}
{\color{red}\begin{lstlisting}[language=C, caption=C语言指针周期不会被破坏型, label=C.51.2]
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
		
int* ppp()
{
	static int a = 10;
	return &a;
}
		
int main()
{
	int* p = ppp();
	printf("%d\n",*p);
	printf("%d\n",*p);
	printf("%d\n",*p);
	printf("%d\n",*p);
	return 0;
}
\end{lstlisting}}
\subsection{函数返回多个值}
如代码\ref{C.52}里，巧用变量地址，可以使输出的函数值的多个地址变量一起改变，能让函数更加的灵活。
{\color{red}\begin{lstlisting}[language=C, caption=C语言指针的函数返回多个值, label=C.52]
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int Nummer(int arr[], int len,int* max,int* min)
{
	*max = arr[0];
	for (int i = 1; i < len; i++)
	{
		if (*max < arr[i])
		{
			*max = arr[i];
		}
	}
	*min = arr[0];
	for (int i = 1; i < len; i++)
	{
		if (*min > arr[i])
		{
			*min = arr[i];
		}
	}
}

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int len = sizeof(arr) / sizeof(int);
	int max = arr[0];
	int min = arr[0];
	Nummer(arr, len, &max, &min);
	printf("数组的最大值%d\n数组的最小值%d\n",max,min);
	return 0;
}
\end{lstlisting}}
\subsection{函数的结果和计算状态分开}
{\color{red}\begin{lstlisting}[language=C, caption=C语言指针的函数的结果和计算状态分开, label=C.53]
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int Remainder(int num1,int num2,int*res)
{
	if (num2 == 0)
	{
		return 1;
	}
	*res = num1 % num2;
	return 0;
}

int main()
{
	int a = 10;
	int b = 3;
	int res = 0;
	int flag = Remainder(a, b, &res);
	if (!flag) 
	{
		printf("获取到的余数:%d\n",res);
	}
	return 0;
}
\end{lstlisting}}
\subsection{方便操作数组和函数}
{\color{red}\begin{lstlisting}[language=C, caption=C语言指针方便操作数组和函数, label=C.54]
\end{lstlisting}}
\part{EasyX图形库}
\chapter{EasyX的基本语法使用方法}
\part{C语言的项目}
\chapter{猜数字游戏}
\chapter{扫雷游戏}
\section{实现思路}
如果我们要写一个扫雷游戏，首要的就是想到利用数组来存储一系列数据，至于$9\times9$的扫雷阵列，我们就要考虑怎么设置雷，设置规则，设置查询已扫部分周围雷的个数，
\subsection{主函数的引导}
C程序一定要有一个{\color{red}\verb|main|}函数，来包含所有的内容，于是我们要先来写一个{\color{red}\verb|int main(){...}|}函数,写到这里，于是乎，我们想到要来写一个菜单，菜单直接写在主函数里面，又太冗长，不太适合阅读，于是我们就要来给他设置一个函数，于是进入下一步，设置要实现程序的主功能的框架，再进行一步一步的完善，使之不仅有骨，而且有肉。
\subsection{菜单}
一个软件还是程序写出来，最终是要用来面向使用者的，或者人的，于是我们需要来进行写一个菜单，来告诉并引导使用者应该怎么选择，这部分实现代码为
\begin{lstlisting}[caption=扫雷游戏的菜单, label=C.LeiEmnu]
	void emnu(void)
	{
		printf("**************************\n");
		printf("**************************\n");
		printf("**       游戏菜单       **\n");
		printf("**************************\n");
		printf("**************************\n");
		printf("** \t1.开始游戏\t**\n");
		printf("**************************\n");
		printf("** \t0.退出游戏游戏\t**\n");
		printf("**************************\n");
	}
\end{lstlisting}
\section{主函数里面的选择内容}
写完菜单了，于是我们就要来进行让{\color{red}\verb|main|}更具体，于是我们要来先来一个死循环{\color{red}\verb|while(1){...}|}，不让这个游戏每进行一次就要退出重新进入，再来写一个选择。使之功能不冲突{\color{red}\verb|switch ...case...defaul|}来进行选择。首先我们要实现一个退出游戏，我们要利用{\color{red}\verb|return|}。如代码\ref{C.Lermain}所示，我们要在选择1之后进入到游戏里面，选择0之后退出游戏，选择其他数字需要重新输入。
\begin{lstlisting}[caption=扫雷游戏的主函数, label=C.Leimain]
#include <stdio.h>
#include <stdlib.h>	
int main()
{
	while (1)
	{
		emnu();
		printf("请选择你要选择的内容：\n");
		int button;
		scanf("%d", &button);
		switch(button)
		{
			case 1:
			printf("开始游戏：\n");
			game();
			break;
			case 0:
			printf("已退出游戏。\n");
			return;
			break;
			default:
			printf("输入错误请重新输入：\n");
			break;
		}
	}
	return 0;
}
\end{lstlisting}
\subsection{游戏函数}
写完了主函数和菜单函数紧接着，我们要来写最主要的游戏函数的实现，首先也是最首要的，是我们前文所提到的，需要数组，那需要几个数组呢？\par
首先，我们是要一个$9\times9$的雷阵，肯定要有$9\times9$的数组，如\ref{fig:99雷}左边的灰色部分，但是如果我们后续点击之后，要查询这个周围有几个雷，如在左下角绿色部分，这个时候白色的区局在我们的$9\times9$数组中根本就不存在，我们就要设置其他规则，再到最下边，最左边，最上边，最右边，和其他三角各自要有各自的规则，这个程序就会变得很复杂，很不利于管理，于是我们就想到上下左右各自扩大一行，以避免出来查询不到的情况，于是我们就要设置到一个$11\times11$的内部的数组，如图\ref{fig:99雷}左边区域的红色外框，于是就有了\ref{fig:99雷}右侧这个内部数组。
于是有:
\begin{lstlisting}[caption=扫雷游戏的游戏函数1, label=C.LeiGame]
	#define ROW 9
	#define COL 9
	
	#define ROWS ROW+2
	#define COLS COL+2
	
	void game(void)
	{
		char mine[ROWS][COLS] = { '0' };//内部数组
		char show[ROWS][COLS] = { '0' };//外部查看数组
	}
\end{lstlisting}
这个函数里面首先定义了两组量，一组的我们现在要设置$9\times9$数字的，一组是我们内部的$11\times11$数组。
\begin{figure}[h] 
	\centering % 居中图形
	\begin{tikzpicture}
		\draw[fill=lightgray] (0,0) rectangle (3.6,3.6);
		\draw[color=lightgray] (0,0) rectangle (3.6,3.6);
		\foreach \x in {.4,.8,1.2,1.6,2.0,2.4,2.8,3.2}
		{
			\draw[color=RubineRed] (\x,-0.4) -- (\x,4);  
		}
		\foreach \x in {.4,.8,1.2,1.6,2.0,2.4,2.8,3.2}
		{
			\draw[color=RubineRed] (-0.4,\x) -- (4,\x);  
		}
		\draw[color=RubineRed] (-.4,-.4) -- (-.4,4)--(4,4) -- (4,-.4)--cycle;
		\draw[color=RubineRed] (0,0) rectangle (-.4,-.4);
		\draw[color=RubineRed] (3.6,3.6) rectangle (4,4);
		\draw[color=RubineRed] (3.6,0) rectangle (4,-.4);
		\draw[color=RubineRed] (0,3.6) rectangle (-.4,4);
		\draw[color=green] (-.4,-.4) rectangle (0.8,0.8);
	\end{tikzpicture}
	\begin{tikzpicture}
		\draw[color=cyan] (1,1.5)--(0,1.5) -- (0,2)--(1,2)--(1,2.2)--(1.8,1.75)--(1,1.3)--cycle;
	\end{tikzpicture}
	\begin{tikzpicture}
		\draw[fill=lightgray] (0,0) rectangle (4.4,4.4);
		\foreach \x in {.4,.8,1.2,1.6,2.0,2.4,2.8,3.2,3.6,4.0}
		{
			\draw[color=RubineRed] (\x,0) -- (\x,4.4);  
		}
		\foreach \x in {.4,.8,1.2,1.6,2.0,2.4,2.8,3.2,3.6,4.0}
		{
			\draw[color=RubineRed] (0,\x) -- (4.4,\x);  
		}
	\end{tikzpicture}
	\caption{$9\times9$的扫雷矩阵需要转成$11\time 11$的扫雷阵列} % 添加标题
	\label{fig:99雷} % 添加标签（可选）
\end{figure}
\subsection{数组初始化}
有了这些数组我们就要让他初始化一下统一格式，于是就要写以下的初始化内容。
\begin{lstlisting}[caption=扫雷游戏的数组初始化, label=C.LAInit]
void ArrInit(char arr[ROWS][COLS], int rows, int cols, char set)
{
	for (int i = 0; i < rows; i++)
	{
		for (int j = 0; j < cols; j++)
		{
			arr[i][j] = set;
		}
	}
}
\end{lstlisting}
\subsection{数组的打印}
把这个数组初始化，完成，我们就要开始打印这个数组外部给别人看到的，和我们自己内部要看到的两个数组，便于我们代码的调试，修改。
\begin{lstlisting}[caption=扫雷游戏的打印, label=C.LAPrint]
	void ArrPrint(char arr[ROWS][COLS], int row, int col)
	{
		printf("\n--------扫雷-------\n\n");
		for (int i = 0; i <= col; i++)
		{
			printf("%d ", i);
		}
		printf("\n");
		for (int i = 1; i <= row; i++)
		{
			printf("%d ", i);
			for (int j = 1; j <= col; j++)
			{
				printf("%c ", arr[i][j]);
			}
			printf("\n");
		}
	}
\end{lstlisting}
这个函数将行号列号都打印出来了，这样子在后面实现一个数周围雷数量的函数，更好的查看坐标。
\subsection{游戏函数再次丰富}
我们将上方所写的打印函数写到{\color{red}\verb|game|}函数里面，于是我们就得到了以下的内容，就可以在终端打印出来，这样就方便我们调试和使用者使用了。
\begin{lstlisting}[caption=游戏函数2, label=C.LeiGame2]	
void game(void)
{
	char mine[ROWS][COLS] = { '0' };//内部数组
	char show[ROWS][COLS] = { '0' };//外部查看数组
		
	ArrInit(mine, ROWS, COLS, '0');//给内部自己需要查看调试的函数初始化为0
	ArrInit(show, ROWS, COLS, '*');//给外部使用者看的内容初始化为*，保持神秘感
		
	ArrPrint(show, ROW, COL);//给使用者进行查看的
		
	ArrPrint(mine, ROW, COL);//打印出供给后部人员查看的，便于调试
}
\end{lstlisting}
\subsection{随机雷阵}
再来写一个随机雷阵函数（一定要用到随机数种子生成），我们就要引入两个头文件里面的内容：{\color{red}\verb|#include <time.h>|}和{\color{red}\verb|#include <stdlib.h>|}的随机数生成方案，随机生成几个需要的位置，使之成为字符1，与非雷来做区分，我这里是使用了10个雷在后买那使用{\color{red}\verb|if|}来判断，避免两个1重叠，导致少一个数生成。
\begin{lstlisting}[caption=扫雷游戏雷的随机排, label=C.LSet]
void SetMine(char mine[ROWS][COLS], int row, int col)
{
	int count = 0;
	int x = 0;
	int y = 0;
	while (count != EASY_COUNT)
	{
		//生成两个随机数，将这个数组的随机位置埋雷
		x = rand() % row + 1;
		y = rand() % col + 1;
		//避免埋雷位置重复，于是就要写一个判断避免埋的时候重复埋
		if (mine[x][y] != '1')
		{
			mine[x][y] = '1';
			count++;
		}
	}	
}
\end{lstlisting}
这个函数一定是要放在打印数组之前，这样才能一上来就将数组改成已经随机生成的。
\subsection{查询雷个数}
在进行开始找雷的时候，每次找到一个不是雷的坐标，我们就应该在这个坐标输出它周围雷的个数，于是我们就要先事先写出一个，查询9*9矩阵里面有几个雷的函数。\par
首先数字$0\sim9$是ASCll码值是$48\sim57$，所以每次输出雷为‘1’即为49，输出不是雷，即为‘0’，码值为49，于是$49-48=1$于是乎，每次查找到一个值就加一，最后就能得到这个坐标周围存在几个雷了。
\begin{lstlisting}[caption=查询非雷周围雷数, label=C.MineNum]
int MineNum(char mine[ROWS][COLS], int row, int col)
{
	int count = 0;
	for (int i = (row - 1); i <= (row + 1); i++)
	{
		for (int j = (col - 1); j <= (col + 1); j++)
		{
			if (mine[i][j] == '1')
			{
				count += (mine[i][j] - '0');
			}
		}
	}
	return count;
}
\end{lstlisting}
\subsection{排雷}
最后我们需要加上没有雷位置周围雷的个数，并且这个循环应当为当排除了所有雷时候才能结束，且要在输入错误时候重新输入，才能把这个函数写完。
\begin{lstlisting}[caption=查询这个地区是不是雷, label=C.FindMine]
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int win = 0;
	//这个循环一定是很多次
	while (win < (row * col - EASY_COUNT)) 
	{
		printf("请输入你要查看这个数的的坐标(x,y):");
		scanf("%d %d", &x, &y);
		//判断输入的坐标是不是越界了
		if ((x >= 1 && x <= row) && (y >= 1 && y <= col))
		{
			//判断这个坐标是不是雷
			if (mine[x][y] != '1')//如果这个数不是雷那么这个数周围雷的个数是几个
			{
				//由于直接写的话嵌套括号太多，于是我们需要写一个判断雷个数的函数
				int count = MineNum(mine, x, y);
				//在用户选择坐标之后，将这个坐标替换成周围雷的个数
				show[x][y] = count + '0';
				ArrPrint(show, ROW, COL);
				win++;
			}
			else//如果是雷就要游戏结束了
			{
				printf("被雷炸死了，请重新开始这个游戏。\n");
				ArrPrint(mine, ROW, COL);//让人看到这次游戏雷所在的位置
				break;
			}
		}
		else
		{
			printf("输入坐标有错误，请重新输入。\n");
			continue;
		}
	}
	
	if (win == (row * col - EASY_COUNT))
	{
		printf("\n恭喜你排雷成功\n");
		ArrPrint(mine, ROW, COL);
	}
}
\end{lstlisting}
\subsection{最终版的游戏函数}
\begin{lstlisting}[caption=C语言的扫雷游戏, label=C.LeiGame3]
void game(void)
{
	char mine[ROWS][COLS] = { '0' };//内部数组
	char show[ROWS][COLS] = { '0' };//外部查看数组
	
	ArrInit(mine, ROWS, COLS, '0');//给内部自己需要查看调试的函数初始化为0
	ArrInit(show, ROWS, COLS, '*');//给外部使用者看的内容初始化为*，保持神秘感
	
	SetMine(mine, ROW, COL);//将已经初始化中的雷布置好
	
	ArrPrint(show, ROW, COL);//给使用者进行查看的
	//ArrPrint(mine, ROW, COL);//打印出供给后部人员查看的，便于调试
	
	FindMine(mine, show, ROW, COL);//排查雷的个数
	
}
\end{lstlisting}
\section{完整代码}
\begin{lstlisting}[caption=C语言的扫雷游戏, label=C.ShaoLei]
                    /*扫雷游戏*/
/*1.设置一个菜单选1是玩，0是退出，其他数字重新输入
* 2.选择这个游戏是否要开始(一个死循环，输出0则退出这个游戏)
* 3.游戏若是开始,则进入写好的game()函数中
* 5.game函数从上到下的逻辑一定是，创造一个可见数组和一个内部数组
* 其中内部数组可以用符号表示，外部符号也可以用字符数字表示（在底层代码）中
* 都会转化为二进制，电脑是可以识别的（char类型在计算时候，自动转为int类型）
* 4.首先要初始化数组
* 6.随即打印这个数组，便于我们调试
* 7.再则埋雷（随机生成几个雷）
* 8.最后在看选择的坐标地方存在几个雷
* 9.排除所有雷结束游戏
*/

#define _CRT_SECURE_NO_WARNINGS 1

#define ROW 9
#define COL 9

#define ROWS ROW+2
#define COLS COL+2

#define EASY_COUNT 10

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

void emnu(void);

void game(void);

void ArrInit(char arr[ROWS][COLS], int rows, int cols, char res);

void ArrPrint(char arr[ROWS][COLS], int row, int col);

void SetMine(char mine[ROWS][COLS], int row, int col);

int MineNum(char mine[ROWS][COLS], int row, int col);

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

int main()
{
	while (1)
	{
		srand((unsigned int)time(NULL));
		emnu();
		printf("请选择你要选择的内容：\n");
		int button;
		scanf("%d", &button);
		switch(button)
		{
			case 1:
			printf("开始游戏：\n");
			game();
			break;
			case 0:
			printf("已退出游戏。\n");
			return();
			break;
			default:
			printf("输入错误请重新输入：\n");
			break;
		}
	}
	return 0;
}

//打印扫雷游戏的菜单，是整个程序的骨架
void emnu(void)
{
	printf("**************************\n");
	printf("**************************\n");
	printf("**       游戏菜单       **\n");
	printf("**************************\n");
	printf("**************************\n");
	printf("** \t1.开始游戏\t**\n");
	printf("**************************\n");
	printf("** \t0.退出游戏游戏\t**\n");
	printf("**************************\n");
}

//扫雷游戏整个程序的经络，用于连接并且实现骨架的功能
void game(void)
{
	char mine[ROWS][COLS] = { '0' };//内部数组
	char show[ROWS][COLS] = { '0' };//外部查看数组
	
	ArrInit(mine, ROWS, COLS, '0');//给内部自己需要查看调试的函数初始化为0
	ArrInit(show, ROWS, COLS, '*');//给外部使用者看的内容初始化为*，保持神秘感
	
	ArrPrint(show, ROW, COL);//给使用者进行查看的
	
	SetMine(mine, ROW, COL);//将已经初始化中的雷布置好
	
	//ArrPrint(mine, ROW, COL);//打印出供给后部人员查看的，便于调试
	
	FindMine(mine, show, ROW, COL);//排查雷的个数
	
}


//把这个程序的数组初始化
void ArrInit(char arr[ROWS][COLS], int rows, int cols, char set)
{
	for (int i = 0; i < rows; i++)
	{
		for (int j = 0; j < cols; j++)
		{
			arr[i][j] = set;
		}
	}
}

//把这个程序打印出来便于调试
void ArrPrint(char arr[ROWS][COLS], int row, int col)
{
	printf("\n--------扫雷-------\n\n");
	for (int i = 0; i <= col; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (int i = 1; i <= row; i++)
	{
		printf("%d ", i);
		for (int j = 1; j <= col; j++)
		{
			printf("%c ", arr[i][j]);
		}
		printf("\n");
	}
}


//埋雷
void SetMine(char mine[ROWS][COLS], int row, int col)
{
	int count = 0;
	int x = 0;
	int y = 0;
	while (count != EASY_COUNT)
	{
		//生成两个随机数，将这个数组的随机位置埋雷
		x = rand() % row + 1;
		y = rand() % col + 1;
		//避免埋雷位置重复，于是就要写一个判断避免埋的时候重复埋
		if (mine[x][y] != '1')
		{
			mine[x][y] = '1';
			count++;
		}
	}
}


//判断雷个数的函数
int MineNum(char mine[ROWS][COLS], int row, int col)
{
	int count = 0;
	for (int i = (row - 1); i <= (row + 1); i++)
	{
		for (int j = (col - 1); j <= (col + 1); j++)
		{
			if (mine[i][j] == '1')
			{
				count += (mine[i][j] - '0');
			}
		}
	}
	return count;
}

//查找这个选择位置周围有几个雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int win = 0;
	//这个循环一定是很多次
	while (win < (row * col - EASY_COUNT)) 
	{
		printf("请输入你要查看这个数的的坐标(x,y):");
		scanf("%d %d", &x, &y);
		//判断输入的坐标是不是越界了
		if ((x >= 1 && x <= row) && (y >= 1 && y <= col))
		{
			//判断这个坐标是不是雷
			if (mine[x][y] != '1')//如果这个数不是雷那么这个数周围雷的个数是几个
			{
				//由于直接写的话嵌套括号太多，于是我们需要写一个判断雷个数的函数
				int count = MineNum(mine, x, y);
				//在用户选择坐标之后，将这个坐标替换成周围雷的个数
				show[x][y] = count + '0';
				ArrPrint(show, ROW, COL);
				win++;
			}
			else//如果是雷就要游戏结束了
			{
				printf("被雷炸死了，请重新开始这个游戏。\n");
				ArrPrint(mine, ROW, COL);//让人看到这次游戏雷所在的位置
				break;
			}
		}
		else
		{
			printf("输入坐标有错误，请重新输入。\n");
			continue;
		}
	}
	
	if (win == (row * col - EASY_COUNT))
	{
		printf("\n恭喜你排雷成功\n");
		ArrPrint(mine, ROW, COL);
	}
}
\end{lstlisting}
\chapter{XX管理系统}
\end{document}